Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

spring aop源码解析

zhangjie edited this page Dec 10, 2020 · 2 revisions

大致流程主要分为三个步骤

  1. 创建AnnotationAwareAspectJAutoProxyCreator对象
  2. 扫描容器中的切面,创建PointcutAdvisor对象
  3. 生成代理类

创建AnnotationAwareAspectJAutoProxyCreator对象

  1. 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配置
  2. EnableAspectJAutoProxy分析
    -->@Import(AspectJAutoProxyRegistrar.class)
    2.1 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //注册 AnnotationAwareAspectJAutoProxyCreator
    --> 只创建BeanDefinition,并没有实例化和初始化该对象(什么时候触发?)
  3. 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

创建InstantiationModelAwarePointcutAdvisorImpl

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#在postProcessAfterInitialization(IOC最后一个扩展方法)

  1. 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));

获取Advisor对象

  1. 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();
 }
 }

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /