-
Notifications
You must be signed in to change notification settings - Fork 0
spring aop源码解析
zhangjie edited this page Dec 10, 2020
·
2 revisions
- 创建AnnotationAwareAspectJAutoProxyCreator对象
- 扫描容器中的切面,创建PointcutAdvisor对象
- 生成代理类
- spring.factories自动装配
1.1 Auto Configure org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
1.2 该配置类的加载前提是什么?
(1) @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,AnnotatedElement.class })
-->条件注解依赖的配置类均被引入到spring-boot-starter-aop中,只需引入该依赖即可自动装配
(2) spring.aop.auto默认为true,并不需要手动开启
--> 不需要在启动类引入@EnableAspectJAutoPro,保证项目中有spring-boot-starter-aop依赖即可
(3) 最终都会加载@EnableAspectJAutoProxy配置
- EnableAspectJAutoProxy分析
-->@Import(AspectJAutoProxyRegistrar.class)
2.1 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //注册 AnnotationAwareAspectJAutoProxyCreator
--> 只创建BeanDefinition,并没有实例化和初始化该对象(什么时候触发?) - AnnotationAwareAspectJAutoProxyCreator:继承BeanPostProcessor、BeanFactoryAware
3.1 BeanPostProcessor实现类会提前初始化,由postProcessBeforeInstantiation触发
(1) 判断当前bean是否可以被代理,然后存入advisedBeans
1. 判断方法:isInfrastructureClass(beanClass) 、shouldSkip(beanClass, beanName)
1.1 isInfrastructureClass:判定当前类是否有 Aspect 注解,如果有,则不能被代理
1.2 shouldSkip
-->List candidateAdvisors = findCandidateAdvisors(); //获取所有的候选顾问类 Advisor(见创建InstantiationModelAwarePointcutAdvisorImpl)
3.2 BeanFactoryAware在其在实例化 bean 后,会触发setBeanFactory()方法
--> 最终会触发initBeanFactory
(1)this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); //用于创建 advisor
3. List<Advisor> candidateAdvisors = findCandidateAdvisors();
3.1 List<Advisor> advisors = super.findCandidateAdvisors(); //获得 Advisor 实现类
3.2 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); //将@Aspect注解类, 解析成Advisor
(1) String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
-->获取容器中所有的beanName
-->遍历beanNames
1. Class<?> beanType = this.beanFactory.getType(beanName);
2. 如果是Aspect:this.advisorFactory.isAspect(beanType)
2.1 aspectNames.add(beanName);
2.2 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
-->ReflectiveAspectJAdvisorFactory#getAdvisors(见4分析)
===================================================
4. ReflectiveAspectJAdvisorFactory#getAdvisors
4.1 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
--> 从aspectMetadata中获取Aspect()标注的类class对象
4.2 遍历该类的所有方法:getAdvisorMethods(aspectClass)
-->根据方法判断是否能获取到对应 pointCut,如果有,则生成 advisor 对象
(1) Advisor advisor = getAdvisor(method,lazySingletonAspectInstanceFactory,advisors.size(),aspectName);//见5分析
==================================================
5. Advisor advisor = getAdvisor(method,lazySingletonAspectInstanceFactory,advisors.size(),aspectName)
5.1 AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod,
aspectInstanceFactory.getAspectMetadata().getAspectClass());
-->根据候选方法名,来获取对应的 pointCut
5.2 new InstantiationModelAwarePointcutAdvisorImpl
--> 将切点表达式 expressionPointcut、当前对象ReflectiveAspectJAdvisorFactory、方法名等包装成 advisor对象
(1) InstantiationModelAwarePointcutAdvisorImpl的构造方法会触发构造通知对象
-->this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);//见6分析
================================================
6. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
-->ReflectiveAspectJAdvisorFactory#getAdvice
6.1 根据注解类型:aspectJAnnotation.getAnnotationType(),匹配对应的通知类型
(1) 通知类型:AtBefore(前置通知)
AtAfter(最终通知)
AtAfterReturning(后置通知)
AtAfterThrowing(异常通知)
AtAround(环绕通知)
AtPointcut(切面)
(2) 根据@Aspect类中方法的注解类型,生成对应的advice
-->例如:@Aroud -->springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory)
- AbstractAutoProxyCreator#wrapIfNecessary
1.1 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//见下:获取Advisor对象
-->如果获取到advice,则生成代理类
1.2 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
1.1 List candidateAdvisors = findCandidateAdvisors();
(1) List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
-->这里会对获取的advisor进行筛选
1.筛选规则:AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)
-->canApply(candidate, clazz, hasIntroductions)
--> 遍历被代理类的所有的方法,跟进切面表达式进行匹配,如果有一个方法匹配到,也就意味着该类会被代理
-->AopUtils#canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)
(2) extendAdvisors(eligibleAdvisors); //添加一个默认的advisor,执行时用到
1. 接口
public interface UserService {
public void findUser();
}
2. 实现类
public class UserServiceImpl implements UserService {
@Override
public void findUser() {
System.out.println("findUser...");
}
}
3. 2个增强
// 前置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("before log...");
}
}
// 后置增强
public class LogAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("after log...");
}
}
4. 测试
public class UserServiceImplImplTest {
@Test
public void findUser() {
// 1. 创建代理工厂
ProxyFactory factory = new ProxyFactory();
// 2. 设置代理目标对象
factory.setTarget(new UserServiceImpl());
// 3. 设置接口
factory.setInterfaces(new Class[]{UserService.class});
// 4. 设置增强
factory.addAdvice(new LogBeforeAdvice());
factory.addAdvice(new LogAfterAdvice());
// 5. 获取代理对象
UserService userService = (UserService) factory.getProxy();
userService.findUser();
}
}