@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}.
* 默认false,采用JDK动态代理织入增强(实现接口的方式);如果设为true,则采用CGLIB动态代理织入增强
*/
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
* 默认false,设置为true意味着proxy代理会暴露到AOP框架之外,但是并不保证通过AopContext访问使用是正确的
*/
boolean exposeProxy() default false;
}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
/**
*我们看到方法名称的含义是在需要的情况下注册一个切面代理(大概这个意思吧)
*我们推测注册逻辑是在这个方法里面,跟进。
*/
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
@Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//1.判断是否已经注册了一个bean定义信息,名字是 AUTO_PROXY_CREATOR_BEAN_NAME ="org.springframework.aop.config.internalAutoProxyCreator"
//第一次肯定没有,因此这个逻辑第一次会跳过
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//2.根据传进来的类创建beanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
//3.设置相关属性
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//4.注册beanDefinition,bean的名称是"org.springframework.aop.config.internalAutoProxyCreator"
//之后容器中会注册一个AnnotationAwareAspectJAutoProxyCreator.class类型的bean,beanName为org.springframework.aop.config.internalAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
//5.这里返回值不重要,关键是第四步骤注册bean定义
return beanDefinition;
}
[外链图片转存失败(img-dPPBng37-1569065835582)(https://note.youdao.com/yws/api/personal/file/BD8FA85560E24E13B2F0A20659E89363?method=download&shareKey=2da8f90e6e9d4bb7c32079c30a15520a)]
AbstractApplicationContext#refresh //刷新创建容器
->AbstractApplicationContext#registerBeanPostProcessors //注册bean的后置处理器
->PostProcessorRegistrationDelegate#registerBeanPostProcessors()PriorityOrdered->Ordered->others // 按照优先级注册Bean
//我们知道AnnotationAwareAspectJAutoProxyCreator是实现了Order接口的,因此我们调试一次看在什么时候注册
->在代码beanFactory.getBean(ppName, BeanPostProcessor.class)处,回去创建Bean,后面创建Bean的流程和普通bean几乎是一样的-
->AbstractBeanFactory#getBean() //Bean工厂获取bean
->AbstractBeanFactory#doGetBean //Bean工厂获取Bean
->AbstractAutowireCapableBeanFactory#createBean() //创建Bean实例
->AbstractAutowireCapableBeanFactory#doCreateBean //创建Bean实例
->AbstractAutowireCapableBeanFactory#populateBean //Bean属性赋值
->AbstractAutowireCapableBeanFactory#initializeBean() //Bean初始化 (invokeAwareMethods,applyBeanPostProcessorsBeforeInitialization,invokeInitMethods,applyBeanPostProcessorsAfterInitialization)
->创建Bean成功
在PostProcessorRegistrationDelegate中beanFactory.addBeanPostProcessor添加到BeanFactory
AbstractApplicationContext#refresh //刷新创建容器
->AbstractApplicationContext#finishBeanFactoryInitialization //实例化懒加载Bean,通常业务Bean就在这一步实例化
->AbstractApplicationContext#finishBeanFactoryInitialization //实例化单例Bean
->ConfigurableListableBeanFactory#preInstantiateSingletons //实例化剩余的费非懒加载Bean
->DefaultListableBeanFactory#preInstantiateSingletons // 实例化单例Bean
->AbstractBeanFactory#getBean() //Bean工厂获取Bean -- 这一步开始和前面的BeanPostProcessor流程一样了
->AbstractBeanFactory#doGetBean //Bean工厂获取Bean
->AbstractAutowireCapableBeanFactory#createBean()//创建Bean实例,在createBean()方法里面注意了,这后面的流程会不一样
->AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation //调用before-instantiation post-processors,这里并不会创建bean成功
->AbstractAutowireCapableBeanFactory#doCreateBean //创建Bean实例
->AbstractAutowireCapableBeanFactory#populateBean //Bean属性赋值
->AbstractAutowireCapableBeanFactory#initializeBean() //Bean初始化
->AbstractAutowireCapableBeanFactory#invokeAwareMethods //Aware方法调用
->AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization //BeanPosProcessor前置处理(但是这里面没有改变被代理的bean),
->AbstractAutowireCapableBeanFactory#invokeInitMethods //初始化方法调用(init-method,InitializingBean接口afterPropertiesSet方法)
->AbstractAutoProxyCreator#postProcessAfterInitialization //BeanPosProcessor后置处理(这里面返回了被代理的bean对象)
->AbstractAutoProxyCreator#wrapIfNecessary //尝试返回bean
->AbstractAutoProxyCreator#createProxy // 尝试创建bean代理对象
->在createProxy里面创建bean的代理对象成功
@Before("pointCut()")
public void logBefore() {
System.out.println("log @Before...");
}
连接点(joinpoint):能够插入切面的点,简单来说就是能够被我们增强的点。因为并非所有的时机都能被增强,比较典型的有方法调用前后,抛出异常时,我们总是在这些连接点里面去找到我们感兴趣的点来做增强,在Spring中连接点都是方法。在Java代码中连接点是一个接口,实现类不多,比如ReflectiveMethodInvocation是一个,AOP中调用增强方法就是使用该类实例来实现的。
切点(pointcut):切点就是连接点里面的一个子集,切点用来描述连接点,复合描述的就做增强,反之就不做增强。比如我对方法调用前和抛出异常感兴趣,这两个连接点就是我关注的切点,它定义了“何处”。如下就是一个切点描述
@Pointcut("execution(public int com.intellif.ch10.MyTarget.*(..))")
编译期: 切面在目标类编译时期被织入,这种方式需要特殊编译器。AspectJ的织入编译器就是以这种方式织入切面。
类加载期:切面在类加载到JVM ,这种方式需要特殊的类加载器,他可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5 的 LTW 就支持这种织入方式
运行期: 切面在应用运行期间的某个时刻被织入。一般情况下,在织入切面时候,AOP 容器会为目标对象动态的创建代理对象。Spring AOP 就是以这种方式织入切面。