1.注解开启AOP的方式
一般在注解配置的spring项目中,一般只需要在会被spring扫描到并注册的类上加上@EnableAspectJAutoProxy 接口
@Component
@EnableAspectJAutoProxy
public class AopConfig {
}
2.@EnableAspectJAutoProxy源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@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;
}
可以看到导入了 AspectJAutoProxyRegistrar 这个类。
3.AspectJAutoProxyRegistrar源码
可以看到导入的AspectJAutoProxyRegistrar 类实现了ImportBeanDefinitionRegistrar,实现了registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry),
那么ConfigurationClassPostProcessor在解析@Import注解的时候,发现导入的类是ImportBeanDefinitionRegistrar类型,会在实例化这个类后,调用它的
registerBeanDefinitions方法,
-
第一个参数AnnotationMetadata对象为导入他的类的元数据对象,也就是可以拿到@EnableAspectJAutoProxy这个注解具体的配置,如proxyTargetClass属性,以结合beanClass的接口实现情况,决定使用jdk动态代理还是cglib。上诉方法中会把proxyTargetClass属性值设置到一个BeanDefinition对象的属性里。
-
第二个参数BeanDefinitionRegistry对象,拿到了肯定要往里面搞东西了,就是 注册其他更重要的类。
4.注册AnnotationAwareAspectJAutoProxyCreator类
看下AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);注册了什么类进去
可以看到会注册AnnotationAwareAspectJAutoProxyCreator类进去
构建该类的RootBeanDefinition对象,注册到容器中
这个类就是 支持aop的类了。
4.1AnnotationAwareAspectJAutoProxyCreator类
类图
可以看到 继承了spring最重要的BeanPostProcessor接口
那么它会重写postProcessAfterInitialization方法, 在每个bean 实例化,依赖注入,初始化后,调用这个方法,去判断这个bean是否匹配切面, 匹配的话生成并返回它的代理对象,最终加入到spring单例池中的 就是代理对象。
该方法在他的父类AbstractAutoProxyCreator里:
该方法调用的时机
在bean实例化,调用完afterPropertiesSet(),@InitMethod方法之后