SpringAOP实现源码解读

本文章的目标,是给大家分享Spring底层,是怎么样创建目标对象的代理对象,实现Spring AOP的。
为了方便大家根据自己情况,有针对性的进行阅读理解,特意整理了一下如下分享思路,仅供参考,谢谢!
1、Spring AOP样例br/>简单介绍怎么样基于Spring实现AOP编程(注解方式在目标对象方法中织入通知方法)
2、AOP关键注解@EnableAspectJAutoProxy
分析@EnableAspectJAutoProxy注解源,了解实现AOP需要给容器提供的配置信息
3、AOP实现的关键类AnnotationAwareAspectJAutoProxyCreator
静态分析Spring框架里面,创建AOP代理对象的类
4、AnnotationAwareAspectJAutoProxyCreator的实例化和注册
动态分析AnnotationAwareAspectJAutoProxyCreator在容器中的实例化和注册过程
5、AnnotationAwareAspectJAutoProxyCreator创建目标代理对象
动态分析Spring容器使用AnnotationAwareAspectJAutoProxyCreator创建目标代理对象过程

1、Spring AOP样例

本样例代码工程,是基于Maven的,使用的是Spring5.0.5版本,pom.xml如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
<modelVersion>4.0.0</modelVersion>
<groupId>cn.com.tuling.openclass.aop</groupId>
<artifactId>explore-06-spring-aop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.version>5.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

当前样例比较简单,直接贴代码如下:
1)IPowerService和PowerServiceImpl
目标类的接口和实现,里面就一个login方法,将用来织入AOP的通知方法

package cn.com.tuling.openclass.service;
public interface IPowerService {
public boolean login(String userName,String password);
}

package cn.com.tuling.openclass.service.impl;
import org.springframework.stereotype.Service;
import cn.com.tuling.openclass.service.IPowerService;br/>@Service
public class PowerServiceImpl implements IPowerService {
br/>@Override
public boolean login(String userName, String password) {
boolean bool = false;
System.out.println("to execute PowerServiceImpl.login() method...");
bool = userName != null && userName.startsWith("zhang");
return bool;
}
}

2)LogServiceImpl
这里面定义了几个日志方法,以便封装成通知,织入到切入点中

package cn.com.tuling.openclass.service.impl;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;br/>@Component//声明当前类为组件类
@Aspect//切面
public class LogServiceImpl{
//定义切入点
@Pointcut("execution( cn.com.tuling...*(..))")
public void myPointCut(){}

//将logBefore方法封装成Before通知,织入到myPointCut()切入点br/>@Before("myPointCut()")
public void logBefore() {
System.out.println("....logServiceImpl.logBefore....");
}

//将logAfter方法封装成After通知,织入到myPointCut()切入点br/>@After("myPointCut()")
public void logAfter() {
System.out.println("....logServiceImpl.logAfter....");
}

//将logReturnAfter方法封装成AfterReturning通知,织入到myPointCut()切入点br/>@AfterReturning("myPointCut()")
public void logReturnAfter() {
System.out.println("....logServiceImpl.logReturnAfter....");
}

//将logThrowing方法封装成AfterThrowing通知,织入到myPointCut()切入点br/>@AfterThrowing("myPointCut()")
public void logThrowing() {
System.out.println("....logServiceImpl.logThrowing....");
}
}

3)ConfigAOP
Spring注解式配置类

package cn.com.tuling.openclass.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;br/>@Configuration//声明当前类为Spring注解配置类
@EnableAspectJAutoProxy//支持AspectJ注解
br/>@ComponentScan(basePackages="cn.com.tuling.openclass")//自动扫描组件路径
public class ConfigAOP {
}

4)TestAOP,测试类

package cn.com.tuling.openclass.service;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import cn.com.tuling.openclass.config.ConfigAOP;
public class TestAOP {br/>@Test
public void test01(){
// 初始化注解式IOC容器
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigAOP.class);
// 从容器中获取PowerService实例
IPowerService powerService = (IPowerService)ctx.getBean(IPowerService.class);
// 调用PowerService的login方法
boolean bool = powerService.login("zhangsan", "123");
// 关闭IOC容器
ctx.close();
}
}

运行TestAOP里面的test01方法,运行如下日志:
SpringAOP实现源码解读
我们在TestAOP的test01方法中,只是调用了IPowerService的login方法,却在它前后输出了每个通知的打印,说明已经基于Spring的AOP,完成了通知到目标切入点的织入。

2、AOP关键注解@EnableAspectJAutoProxy

通过调整我们前面的ConfigAOP类的代码,我们能感觉到,如果注释掉ConfigAOP类上面的@EnableAspectJAutoProxy,运行TestAOP的test01方法的时候,将看不到通知织入的效果(只会执行PowerServiceImpl中的login方法,不会执行LogServiceImpl中对应的通知方法),说明@EnableAspectJAutoProxy注解里面,定义了SpringAOP织入通知的关键信息,这信息是什么呢,我们来研究@EnableAspectJAutoProxy的源码。

package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**

  • 支持AspectJ注解,使用注解的方式实现AOP织入,效果等同xml配置文件中的<aop:aspectj-autoproxy/>
  • @author Chris Beams
  • @author Juergen Hoeller
  • @since 3.1
  • @see org.aspectj.lang.annotation.Aspectbr/>*/
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    br/>@Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
    /**

    • Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    • to standard Java interface-based proxies. The default is {@code false}.
      */
      boolean proxyTargetClass() default false;

    • Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
    • for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
    • Off by default, i.e. no guarantees that {@code AopContext} access will work.
    • @since 4.3.1
      */
      boolean exposeProxy() default false;
      }

通过查看@EnableAspectJAutoProxy源码,我们了解到@EnableAspectJAutoProxy的作用,同xml配置文件中的<aop:aspectj-autoproxy>一样,告诉Spring容器,支持注解式Aspect。br/>@EnableAspectJAutoProxy有两个属性:
1)proxyTargetClass 指定是否使用CGLIB的方式创建实现接口的目标对象的代理。缺省值为false,使用JDK方式创建接口对象的代理
2) exposeProxy 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
exposeProxy属性的使用案例,请查看另外一个专题(《坑、坑、坑,同一个类中的切入方法无效!》),这里就不重复了。

通观前面的代码,没有哪个地方有描述怎么样实现AOP,不过有发现红色代码行,从名字上就同咱们的目标AOP(AspectJ切面)有关系,我们跟进去,看AspectJAutoProxyRegistrar类源代码如下:

package org.springframework.context.annotation;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
/**

跟到AopConfigUtils源代码中,我们发现最终会调用红色标记部分的代码,该行代码的作用,是在容器中注册一个AspectJAwareAdvisorAutoProxyCreator类。
到这里,我们就找到了SpringAOP中,创建目标对象的代理对象的源(作俑者)。这个作俑者是在@EnableAspectJAutoProxy中告知Spring IOC容器的,也就是说,通过@EnableAspectJAutoProxy注解,通知Spring容器在需要的时候,使用AspectJAwareAdvisorAutoProxyCreator对象创建目标的代理对象,实现通知的织入(实现AOP)。

4、AnnotationAwareAspectJAutoProxyCreator的实例化和注册

到现在,我们根据源代码的摸索,基本上找到了实现AOP的关键类AspectJAwareAdvisorAutoProxyCreator,那这个类的对象什么时候实例化,又在什么时候创建的AOP代理对象的呢?能回答出这个问题,咱们的AOP原理是不是就搞定了呀 ^_^
接下来我们先研究AspectJAwareAdvisorAutoProxyCreator对象的创建过程。
我们在TestAOP的test01方法里的AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigAOP.class);代码上,添加一个debug,用debug的方式,跟进代码,历经如下:
AnnotationConfigApplicationContext.AnnotationConfigApplicationContext(Class ... annotatedClasses)
->AbstractApplicationContext.refresh()
refresh方法的代码如下:

        // 初始化容器上下文(比如容器启动时间等)
        prepareRefresh();
        // 创建beanFactory容器对象,以前有销毁再创建,以前没有,创一个新对象
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 初始化beanFactory.(类加载器、Application...Processor、Aware、环境对象等)
        prepareBeanFactory(beanFactory);
        try {
            // 模板方法,在Bean定义加载完后,为子类提供一个可以修改BeanFactory的入口
            postProcessBeanFactory(beanFactory);
            // 调用注册在容器中的BeanFactory处理器
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注册Bean后置处理器,这些处理器会在创建Bean对象的时候被调用
            registerBeanPostProcessors(beanFactory);
            // 初始化资源
            initMessageSource();
            // 初始化容器的事件广播器
            initApplicationEventMulticaster();
            // 模板方法,给子类提供一个在容器中实例化其他特殊bean的机会
            onRefresh();
            // 检测并注册监听器
            registerListeners();
            // 实例化其他的非延时加载的单例对象.
            finishBeanFactoryInitialization(beanFactory);
            // 发布容器事件
            finishRefresh();
        }
                  ... ...

通过查看AspectJAwareAdvisorAutoProxyCreator的父类和实现类,我们可以发现AspectJAwareAdvisorAutoProxyCreator实际上是一个BeanPostProcessor子类,所以在Spring中,是在refresh方法中标红语句(registerBeanPostProcessors)的方法中完成的。我们debug到registerBeanPostProcessors方法中去,路径如下:
AnnotationConfigApplicationContext(AbstractApplicationContext).refresh() line: 535
->AnnotationConfigApplicationContext(AbstractApplicationContext).registerBeanPostProcessors(ConfigurableListableBeanFactory) line: 710
->PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext) line: 189
PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)方法的代码如下:

    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List&lt;BeanPostProcessor&gt; priorityOrderedPostProcessors = new ArrayList&lt;&gt;();
    List&lt;BeanPostProcessor&gt; internalPostProcessors = new ArrayList&lt;&gt;();
    List&lt;String&gt; orderedPostProcessorNames = new ArrayList&lt;&gt;();
    List&lt;String&gt; nonOrderedPostProcessorNames = new ArrayList&lt;&gt;();
    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);
        }
    }
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    // Next, register the BeanPostProcessors that implement Ordered.
    List&lt;BeanPostProcessor&gt; orderedPostProcessors = new ArrayList&lt;&gt;();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);①
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);②
    // Now, register all regular BeanPostProcessors.
    List&lt;BeanPostProcessor&gt; nonOrderedPostProcessors = new ArrayList&lt;&gt;();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    // Finally, re-register all internal BeanPostProcessors.
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

上面的代码,大概思路是这样的:
1)获取容器中的所有BeanPostProcessor的beanName,也就是咱们在Spring容器中注册bean时的id或name
2)根据BeanPostProcessor是否实现了PriorityOrdered、Ordered、普通BeanPostProcessor对Processor进行分类
3)按PriorityOrdered、Ordered、普通种类的顺序,初始化并注册对应的BeanPostProcessor
我们可以查看一下AnnotationAwareAspectJAutoProxyCreator的父类,会发现它是实现了Ordered接口的(实际上ProiorityOrdered也是Ordered的子类),所以AnnotationAwareAspectJAutoProxyCreator对象是在上面红色标记的①代码实例化的,在②代码注册到beanFactory中的。其中beanFactory.getBean(..)方法,是Spring获取对象的统一方式,详细过程,我们在后面进行代码跟踪,这里咱们暂时记住getBean方法里面,完成了AnnotationAwareAspectJAutoProxyCreator对象的创建,并通过② 代码完成了AnnotationAwareAspectJAutoProxyCreator的注册(在容器中创建了对象,并且保存下来,beanName是org.springframework.aop.config.internalAutoProxyCreator)

5、AnnotationAwareAspectJAutoProxyCreator创建目标代理对象

前面我们了解了Spring创建和注册AnnotationAwareAspectJAutoProxyCreator对象的过程,在这小节,我们将研究Spring是怎样使用注册好的AnnotationAwareAspectJAutoProxyCreator对象创建AOP代理对象的。
在我们的案例中,PowerServiceImpl对象是要织入通知的目标对象,接下来我们跟踪PowerServiceImpl对象的实例化和创建AOP代理对象的过程。
跟踪第4小节,AbstractApplicationContext.refresh()方法中的finishBeanFactoryInitialization(beanFactory);代码(PowerServiceImpl属于非延时加载的代理对象,所以在这行代码里面完成实例化)


    因为AOP的代理创建,是在SpringIOC容器初始化的时候实现的,为了方便找到PowerServiceImpl的AOP代理对象的创建代码,我们在TestAOP的test01方法里的AnnotationConfigApplicationContext  ctx = new  AnnotationConfigApplicationContext(ConfigAOP.class);代码上,添加一个debug,用debug的方式,跟进代码,历经如下:
     AnnotationConfigApplicationContext.<init>(Class<?>...) line: 88    
      ->AbstractApplicationContext.refresh() line: 550    
        ->AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 869    
           ->DefaultListableBeanFactory.preInstantiateSingletons() line: 728    
DefaultListableBeanFactory.preInstantiateSingletons()方法的代码块如下:
if (this.logger.isDebugEnabled()) {
    this.logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非延时加载的单例对象的实例化
for (String beanName : beanNames) {
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
                final FactoryBean<?> factory = (FactoryBean<?>) bean;
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                    ((SmartFactoryBean<?>) factory)::isEagerInit,
                            getAccessControlContext());
                }
                else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);①
                }
            }
        }
        else {
            getBean(beanName);
        }
    }
}
// 触发所有对应bean初始化后的回调方法
for (String beanName : beanNames) {
    Object singletonInstance = getSingleton(beanName);
    if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                smartSingleton.afterSingletonsInstantiated();
                return null;
            }, getAccessControlContext());
        }
        else {
            smartSingleton.afterSingletonsInstantiated();
        }
    }
}
上面代码主要做两个事情:一个是实例化所有非延时加载的单例对象;一个是调用实例化对象后的回调方法。所有对象的实例化过程,都是在如上代码,红色标记语句①getBean(beanName)完成的。
为了了解AOP代理对象的创建过程,我们需要在getBean(beanName)①;上加上一个debug断点。同时考虑到每个对象都会进入这个断点,进行对象的创建,而我们只关心PowerServiceImpl对象和对应AOP代理对象的创建过程,所以我们可以在getBean()方法的断点上面,加上条件。这样只有符合条件的时候,才会在该断点停下来,方便我们debug进去。
添加条件断点的方式如下:
1)在getBean()行代码前面,双击添加一个断点(位置很重要,注意如下图所示)
 ![](https://s1.51cto.com/images/blog/201905/07/829d8ff8f127d0e43f68b47a9a16ea09.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
2)在断点上点击鼠标右键,选择菜单中的 Breakpoint Properties.. 选项
      ![](https://s1.51cto.com/images/blog/201905/07/07fc57779f666abbf1bea1032b99a292.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
  3)点击Breakpoint Properties..选项,进入属性设置页面,选择conditional选项,同事在条件输入框中输入条件语句。入下图:
         ![](https://s1.51cto.com/images/blog/201905/07/f395f0d5094c9abbc7eda4be1fb11cbd.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
   4)点击OK按钮,清除其他断点()只留当前加上的条件断点),重新debug运行TestAOP的test01方法

    从前面加上的条件断点开始,逐步debug进去,debug的线路如下(第一次debug不妨按如下的参考进行,先确定AOP对象创建的位置,回过来再了解每个过程中涉及方法的逻辑流程):
    DefaultListableBeanFactory.preInstantiateSingletons() line: 760    
    ->AbstractBeanFactory.getBean(String) line: 199    
        ->AbstractBeanFactory.doGetBean(String, Class<T>, Object[], boolean) line: 315    
            ->DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>) line: 228    
                ->AbstractBeanFactory.lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 317   
                    ->AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[]) line: 501   
                        ->AbstractAutowireCapableBeanFactory.doCreateBean(...) line: 579    
                            ->AbstractAutowireCapableBeanFactory.initializeBean(...) line: 1706    
                                ->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(.) line: 436 
   到这一步,就进入了Spring容器中,给PowerServiceImpl创建AOP代理对象的过程,前面分析@EnableAspectJAutoProxy源码的时候,咱们知道在AspectJAutoProxyRegistrar类中,有注册了一个AnnotationAwareAspectJAutoProxyCreator类,并且也初步告诉大家,Spring在初始化容器的时候,会根据需要,使用该类的对象,创建AOP代理对象,完成通知到目标切入点方法的织入。该动作就在AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(.)方法中完成的。
   我们查看AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(.)方法里面的源代码如下:
> public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
>         throws BeansException {
>     Object result = existingBean;
>     for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {                   ①
>         Object current = beanProcessor.postProcessAfterInitialization(result, beanName);②
>         if (current == null) {
>             return result;
>         }
>         result = current;
>     }
>     return result;
> }
    通过阅读上面的源代码,我们可以了解到,该代码是获取容器中所有有注册的BeanPostProcessor(Bean后置处理器),循环的调用每个BeanPostProcessor(Bean后置处理器)的postProcessAfterInitialization方法,对当前的目标对象进行处理(beanName对应的对象)。选择上面代码①行的getBeanPostProcessors()部分代码,点击鼠标右键,选择Wath选项,如图:
![](https://s1.51cto.com/images/blog/201905/07/b5800891aec013b48fc5e52278138a27.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
点击Watch选项,进入Debug窗口的Expression视图,可以看到getBeanPostProcessors()方法能获取到的,将要遍历调用的所有Bean后置处理器,其中第四个,就是AnnotationAwareAspectJAutoProxyCreator,如下图:
![](https://s1.51cto.com/images/blog/201905/07/a781dea5f323bc802f5f27a005c5228a.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
我们循环到第四个后置处理器,继续debug进去,如:
AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(Object, String) line: 437    
->AnnotationAwareAspectJAutoProxyCreator(AbstractAutoProxyCreator).postProcessAfterInitialization(..) line: 304    
    ->AnnotationAwareAspectJAutoProxyCreator(AbstractAutoProxyCreator).wrapIfNecessary(... ...) line: 340    
在wrapIfNecessary(...)方法中,有如下关键代码:
> // 获取要织入到beanName目标对象的切入点的所有通知
> Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);  ①
> if (specificInterceptors != DO_NOT_PROXY) {
>     this.advisedBeans.put(cacheKey, Boolean.TRUE);
>     // 创建代理对象
>     Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));  ②
>     this.proxyTypes.put(cacheKey, proxy.getClass());
>     return proxy;
> }
其中①代码是获取要织入到目标切入点中的所有通知(拦截器对象),我们用Debug中查看变量值的方式,查看specificInterceptors中的所有拦截器对象,如图:
![](https://s1.51cto.com/images/blog/201905/07/e53abde5b12b670de826776054418c87.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
一共有5个通知对象,除了第一个默认通知对象外,剩下4个,都是我们再LogServiceImpl类中,有用通知注解标记后的通知对象,分别是@Before,@After,@AfterReturning和@AfterThrowing,在上图中,标记了@AfterThrowing的关键信息。
真正创建AOP代理对象,完成通知织入动作,是在②行代码,接下来我们继续从②开始Debug进去,过程如:
AbstractAutoProxyCreator.wrapIfNecessary(Object, String, Object) line: 356    
->AbstractAutoProxyCreator.createProxy(Class<?>, String, Object[], TargetSource) line: 473    
    ->ProxyFactory.getProxy(ClassLoader) line: 110    
        ->ProxyFactory(ProxyCreatorSupport).createAopProxy() line: 105    
在ProxyCreatorSupport.createAopProxy()方法中,有对ProxyFactory中对AOP创建条件进行了判断(比如在@EnableAspectJAutoProxy注解中,是否有设置proxyTargetClass属性为true等),决定使用CGLIB还是JDK创建AOP代理对象。具体流程,请查看createAopProxy()方法中的源代码和中午注释,如:
> if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { ①
>     Class<?> targetClass = config.getTargetClass();
>     if (targetClass == null) {
>         throw new AopConfigException("TargetSource cannot determine target class: " +
>                 "Either an interface or a target is required for proxy creation.");
>     }
>     if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {    ①
>         // 返回基于JDK产生的动态代理对象
>         return new JdkDynamicAopProxy(config);   ②
>     }
>     // 返回基于CGLIB产生的动态代理对象
>     return new ObjenesisCglibAopProxy(config);   ③
> }
> else {
>     // 返回基于JDK产生的动态代理对象
>     return new JdkDynamicAopProxy(config);        ④
> }
我们当前的PowerServiceImpl对象,是面向接口编程的,而且也没有在@EnableAspectJAutoProxy注解中声明属性,当前代码会执行④行代码,我们继续Debug进去,路线如:
DefaultAopProxyFactory.createAopProxy(AdvisedSupport) line: 63    
->ProxyFactory(ProxyCreatorSupport).createAopProxy() line: 105    
    ->ProxyFactory.getProxy(ClassLoader) line: 110    
        ->JdkDynamicAopProxy.getProxy(ClassLoader) line: 123    
这时候就进入了JDK里面的java.lang.reflect.Proxy类,进行SpringAOP的动态对象的创建(AOP代理对象),我们就找到了Spring中使用AnnotationAwareAspectJAutoProxyCreator组件,完成AOP代理对象的创建过程。

6 总结
   通过前面的源代码的风险和跟踪,可以得出如下结论
   1)通过在配置类上面添加@EnableAspectJAutoProxy注解,通知Spring容器支持注解AspectJ,实现面向AOP编程
   2)使用@Aspect、@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing和@Arount注解,完成切面的声明,切入点的声明和各种通知的声明
   3)Spring容器中,是通过AnnotationAwareAspectJAutoProxyCreator对象,在目标对象初始化完后,利用BeanPostProcessor后置通知的机制,完成对目标对象的AOP对象创建
   4)AnnotationAwareAspectJAutoProxyCreator对象内部,是封装JDK和CGlib两个技术,实现动态代理对象创建的
   5)Spring里面,使用JDK还是CGLIB,可以在@EnableAspectJAutoProxy中设置proxyTargetClass属性指定,也可以通过Spring自己判断,目标对象类是否实现了接口,有实现接口,就使用JDK,否则就使用CGLIB

转载于:https://blog.51cto.com/14295469/2390478

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值