【Spring源码解析】 – AOP注入IOC && Bean是如何被增强的

导读:本篇文章讲解 【Spring源码解析】 – AOP注入IOC && Bean是如何被增强的,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1 AOP 入门

1.1 AOP概念

面向切面编程,指程序在运行期间动态的将某段代码切入到指定方法位置进行运行的编程方式

1.2 AOP通知方法

前置通知: logStart(),在目标方法(div)运行之前运行 (@Before)
后置通知:logEnd(), 在目标方法(div)运行结束之后运行,无论正常或异常结束 (@After)
返回通知:logReturn, 在目标方法(div)正常返回之后运行 (@AfterReturning)
异常通知:logException, 在目标方法(div)出现异常后运行(@AfterThrowing)
环绕通知:动态代理, 最底层通知,手动指定执行目标方法(@Around)

执行顺序:AroundStart Before AroundEnd After Returing

1.3 demo

(1) pom

 <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
    </dependencies>

(2) 配置文件

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.spring")
public class SpringConfig {

}

(3) 切面类

@Configuration
@Aspect
public class SpringAspects {
    /**
     * 声明切点
     */
    @Pointcut("execution(public int com.spring.service.*.*(..))")
    public void pointCut() {
    }

    /**
     *  前置通知
     */
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
       System.out.println("@Before:" + joinPoint.getSignature().getName()+"  "+ Arrays.asList(joinPoint.getArgs()));
    }

    /**
     * 后置通知
     */
    @After("pointCut()")
    public void after() {
        System.out.println("@After:");
    }

    /**
     * 返回通知
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void returing(Object result) {
        System.out.println("@AfterReturning:" + result);
    }

    /**
     * 异常通知
     */
    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void throwing(Exception exception) {
        System.out.println(" @AfterThrowing:" + exception);
    }


    /**
     * 环绕通知
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("@Around start ");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("proceed: " + proceed);
        System.out.println("@Around end");
        return proceed;
    }
}

(4) service

package com.spring.service;

import org.springframework.stereotype.Service;

@Service
public class CalculatorService {
    public int div(int i, int j) {
        return i / j;
    }
}

(5) 启动类

public class SpringApplicationContext {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        CalculatorService calculatorService = (CalculatorService) applicationContext.getBean("calculatorService");
        calculatorService.div(5, 1);
        applicationContext.close();
    }

}

在这里插入图片描述

2 @EnableAspectJAutoProxy 的作用

在这里插入图片描述
(1) 源码分析,引入了AspectJAutoProxyRegistrar类
在这里插入图片描述
(2)AspectJAutoProxyRegistrar作用分析
AspectJAutoProxyRegistrar作用其实就是给IOC中添加AnnotationAwareAspectJAutoProxyCreator.class(name为,org.springframework.aop.config.internalAutoProxyCreator)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、AOP 核心类分析 AnnotationAwareAspectJAutoProxyCreator

3.1、AnnotationAwareAspectJAutoProxyCreator类关系图

(1)、InstantiationAwareBeanPostProcessor:实现了BeanPostProcessor后置处理器。
(2)、Ordered:IOC初始化时,具有高优先级。
在这里插入图片描述

3.2、AbstractAutowireCapableBeanFactory docreate方法打断点调试

(1) F8一直调到BeanName为org.springframework.aop.config.internalAutoProxyCreator
在这里插入图片描述
(2) 查看调用方法
在这里插入图片描述

(3) 定位到AbstractApplicationContext refresh()方法里面,在registerBeanPostProcessors实现了AOP的Bean的注入。
在这里插入图片描述

4 PostProcessorRegistrationDelegate registerBeanPostProcessors方法作用

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   
    //1 获取所有BeanPostProcessor接口的实现类beanname
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    
    //2 priorityOrderedPostProcessors,类型为PriorityOrdered.class的BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
   
    //3 存储类型为Ordered.class 和 noneOrder类型的Bean名称
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
   
    //4 把 PriorityOrdered.class、Ordered.class、noOrder.class三种类型分开
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    //5 排序,并且注册PriorityOrdered.class类型的到IOC中
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    //6 创建并且把类型为Order.class的BeanPostProcessor存储起来
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
        /**
         * AOP核心类AnnotationAwareAspectJAutoProxyCreator,实现了Order接口,在此通过
         * getBean->doGetBean->createBean->doCreateBean.......创建且加入到IOC中
         */
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }

    //7  Order.class类型的BeanPostProcessor进行排序并且注册到IOC中
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    //8 创建并且把noOrder类型的BeanPostProcessor存储起来
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    //9 排序、注册,nonOrderedPostProcessors类型的Bean
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

5 calculateService加强过程

(1) AbstractAutowireCapableBeanFactory initializeBean 打断点找到CalculatorService的Bean,看是在前置加强还是在后置加强
在这里插入图片描述
(2) 首先找到前置处理器,发现前置处理器没有增强类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3) 后置处理器
跟进去发现是后置处理器增强了bean
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15157.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!