一,@EnableAspectJAutoProxy 注解
在主配置类中添加 @EnableAspectJAutoProxy 注解, 开启 aop 支持, 那么 @EnableAspectJAutoProxy 到底做了什么? 接下来分析下:
@EnableAspectJAutoProxy 点进去如下:
此时看到了我们非常熟悉的 @Import 注解,@Import(AspectJAutoProxyRegistrar.class), 进入到 AspectJAutoProxyRegistrar 发现实现了 ImportBeanDefinitionRegistrar 如下:
- 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);
- }
- }
- }
- }
会调用 registerBeanDefinitions 方法, 跟进到这个方法里面, 主要作用就是往 Spring 容器中注册 AnnotationAwareAspectJAutoProxyCreator 的 Bean 的定义信息:
二, AnnotationAwareAspectJAutoProxyCreator 继承图
三, AnnotationAwareAspectJAutoProxyCreator 创建代理
首先 AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 实现了 BeanFactoryAware 接口:
所以在创建 AnnotationAwareAspectJAutoProxyCreatorBean 的过程中初始化方法里面会调用 setBeanFactory 方法:
在 setBeanFactory 方法里面调用 initBeanFactory 来初始化通知者检索帮助类, 后面检索通知会用到.
- protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
- this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
- }
其次 AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor 接口:
该接口定义了 2 个方法: postProcessBeforeInstantiation 和 postProcessAfterInstantiation, 所以 AbstractAutoProxyCreator 实现了这 2 个方法; 还记得我们在 Spring IoC 源码解析篇分析到如下代码:
resolveBeforeInstantiation 方法进去就会调到 AbstractAutoProxyCreator 的 postProcessBeforeInstantiation 方法
- /**
- * 在创建 Bean 的流程中还没调用构造器来实例化 Bean 的时候进行调用(实例化前后)
- * AOP 解析切面以及事务解析事务注解都是在这里完成的
- * @param beanClass 当前正在创建的 Bean 的 Class 对象
- * @param beanName beanName
- * @return
- * @throws BeansException
- */
- @Override
- public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
- // 构建我们的缓存 key
- Object cacheKey = getCacheKey(beanClass, beanName);
- if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
- // 如果被解析过直接返回
- if (this.advisedBeans.containsKey(cacheKey)) {
- return null;
- }
- /**
- * 判断是不是基础的 Bean(Advice,PointCut,Advisor,AopInfrastructureBean)是就直接跳过
- * 判断是不是应该跳过 (AOP 解析直接解析出我们的切面信息(并且把我们的切面信息进行缓存), 而事务在这里是不会解析的)
- */
- if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return null;
- }
- }
- TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
- if (targetSource != null) {
- if (StringUtils.hasLength(beanName)) {
- this.targetSourcedBeans.add(beanName);
- }
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
- Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
- this.proxyTypes.put(cacheKey, proxy.getClass());
- return proxy;
- }
- return null;
- }
接下来进入到 shouldSkip(beanClass, beanName)方法(很重要):
- protected boolean shouldSkip(Class<?> beanClass, String beanName) {
- /**
- * 找到候选的 Advisors(通知者或者增强器对象)
- */
- List<Advisor> candidateAdvisors = findCandidateAdvisors();
- for (Advisor advisor : candidateAdvisors) {
- if (advisor instanceof AspectJPointcutAdvisor &&
- ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
- return true;
- }
- }
- return super.shouldSkip(beanClass, beanName);
- }
接下来看如何找候选的 Advisors,findCandidateAdvisors()方法如下:
- @Override
- protected List<Advisor> findCandidateAdvisors() {
- // 找出事务相关的 advisor
- List<Advisor> advisors = super.findCandidateAdvisors();
- // 找出 Aspect 相关的信息之后封装为一个 advisor
- if (this.aspectJAdvisorsBuilder != null) {
- advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
- }
- // 返回我们所有的通知
- return advisors;
- }
第一步找事务相关的 Advisor:
- protected List<Advisor> findCandidateAdvisors() {
- Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
- /**
- * 通过通知者检测帮助类来帮助我们找到通知
- *
- */
- return this.advisorRetrievalHelper.findAdvisorBeans();
- }
第二步找构建 AspectJAdvisors:
- /**
- * 去容器中获取到所有的切面信息保存到缓存中
- */
- public List<Advisor> buildAspectJAdvisors() {
- List<String> aspectNames = this.aspectBeanNames;
- // 缓存字段 aspectNames 没有值 注意实例化第一个单实例 bean 的时候就会触发解析切面
- if (aspectNames == null) {
- synchronized (this) {
- aspectNames = this.aspectBeanNames;
- if (aspectNames == null) {
- // 用于保存所有解析出来的 Advisors 集合对象
- List<Advisor> advisors = new ArrayList<>();
- // 用于保存切面的名称的集合
- aspectNames = new ArrayList<>();
- /**
- * AOP 功能中在这里传入的是 Object 对象, 代表去容器中获取到所有的组件的名称, 然后再
- * 进行遍历, 这个过程是十分的消耗性能的, 所以说 Spring 会再这里加入了保存切面信息的缓存.
- * 但是事务功能不一样, 事务模块的功能是直接去容器中获取 Advisor 类型的, 选择范围小, 且不消耗性能.
- * 所以 Spring 在事务模块中没有加入缓存来保存我们的事务相关的 advisor
- */
- String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
- this.beanFactory, Object.class, true, false);
- // 遍历我们从 IoC 容器中获取处的所有 Bean 的名称
- for (String beanName : beanNames) {
- if (!isEligibleBean(beanName)) {
- continue;
- }
- // 通过 beanName 去容器中获取到对应 class 对象
- Class<?> beanType = this.beanFactory.getType(beanName);
- if (beanType == null) {
- continue;
- }
- // 根据 class 对象判断是不是切面 @Aspect
- if (this.advisorFactory.isAspect(beanType)) {
- // 是切面类
- // 加入到缓存中
- aspectNames.add(beanName);
- // 把 beanName 和 class 对象构建成为一个 AspectMetadata
- AspectMetadata amd = new AspectMetadata(beanType, beanName);
- if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
- // 构建切面注解的实例工厂
- MetadataAwareAspectInstanceFactory factory =
- new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
- // 真正的去获取我们的 Advisor
- List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
- // 加入到缓存中
- if (this.beanFactory.isSingleton(beanName)) {
- this.advisorsCache.put(beanName, classAdvisors);
- }
- else {
- this.aspectFactoryCache.put(beanName, factory);
- }
- advisors.addAll(classAdvisors);
- }
- else {
- // Per target or per this.
- if (this.beanFactory.isSingleton(beanName)) {
- throw new IllegalArgumentException("Bean with name'" + beanName +
- "'is a singleton, but aspect instantiation model is not singleton");
- }
- MetadataAwareAspectInstanceFactory factory =
- new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
- this.aspectFactoryCache.put(beanName, factory);
- advisors.addAll(this.advisorFactory.getAdvisors(factory));
- }
- }
- }
- this.aspectBeanNames = aspectNames;
- return advisors;
- }
- }
- }
- if (aspectNames.isEmpty()) {
- return Collections.emptyList();
- }
- List<Advisor> advisors = new ArrayList<>();
- for (String aspectName : aspectNames) {
- List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
- if (cachedAdvisors != null) {
- advisors.addAll(cachedAdvisors);
- }
- else {
- MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
- advisors.addAll(this.advisorFactory.getAdvisors(factory));
- }
- }
- return advisors;
- }
- 1 org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect:
2 真正的去获取我们的 Advisor,this.advisorFactory.getAdvisors(factory)方法如下:
- @Override
- public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
- // 获取我们的标记为 Aspect 的类
- Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
- // 获取我们的切面类的名称
- String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
- // 校验我们的切面类
- validate(aspectClass);
- // 我们使用的是包装模式来包装我们的 MetadataAwareAspectInstanceFactory 构建为 MetadataAwareAspectInstanceFactory
- MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
- new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
- List<Advisor> advisors = new ArrayList<>();
- // 获取到切面类中的所有方法, 但是该方法不会解析到标注了 @PointCut 注解的方法
- for (Method method : getAdvisorMethods(aspectClass)) {
- // 循环解析我们切面中的方法
- Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
- if (advisor != null) {
- advisors.add(advisor);
- }
- }
- if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
- Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
- advisors.add(0, instantiationAdvisor);
- }
- for (Field field : aspectClass.getDeclaredFields()) {
- Advisor advisor = getDeclareParentsAdvisor(field);
- if (advisor != null) {
- advisors.add(advisor);
- }
- }
- return advisors;
- }
获取切面上的通知方法, 并按照规则排序, getAdvisorMethods(aspectClass):
- private List<Method> getAdvisorMethods(Class<?> aspectClass) {
- final List<Method> methods = new ArrayList<>();
- ReflectionUtils.doWithMethods(aspectClass, method -> {
- if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
- methods.add(method);
- }
- });
- methods.sort(METHOD_COMPARATOR);
- return methods;
- }
排序 (该顺序在代理调用的时候会用到) 规则如下:
根据通知的方法创建增强器: getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)如下:
- public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
- int declarationOrderInAspect, String aspectName) {
- validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
- // 切面的方法上构建切点表达式
- AspectJExpressionPointcut expressionPointcut = getPointcut(
- candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
- if (expressionPointcut == null) {
- return null;
- }
- // 实例化我们的切面通知对象
- return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
- this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
- }
实例化我们的切面通知对象, new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName):
- public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
- Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
- MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
- // 当前的切点表达式
- this.declaredPointcut = declaredPointcut;
- // 切面的 class 对象
- this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
- // 切面方法的名称
- this.methodName = aspectJAdviceMethod.getName();
- // 切面方法的参数类型
- this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
- // 切面方法对象
- this.aspectJAdviceMethod = aspectJAdviceMethod;
- //aspectj 的通知工厂
- this.aspectJAdvisorFactory = aspectJAdvisorFactory;
- //aspect 的实例工厂
- this.aspectInstanceFactory = aspectInstanceFactory;
- // 切面的顺序
- this.declarationOrder = declarationOrder;
- // 切面的名称
- this.aspectName = aspectName;
- /**
- * 判断当前的切面对象是否需要延时加载
- */
- if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
- // Static part of the pointcut is a lazy type.
- Pointcut preInstantiationPointcut = Pointcuts.union(
- aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
- // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
- // If it's not a dynamic pointcut, it may be optimized out
- // by the Spring AOP infrastructure after the first evaluation.
- this.pointcut = new PerTargetInstantiationModelPointcut(
- this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
- this.lazy = true;
- }
- else {
- // A singleton aspect.
- this.pointcut = this.declaredPointcut;
- this.lazy = false;
- // 将切面中的通知构造为 advice 通知对象
- this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
- }
- }
将切面中的通知构造为 advice 通知对象, instantiateAdvice(this.declaredPointcut):
获取通知 getAdvice 方法如下:
- public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
- MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
- // 获取我们的切面类的 class 对象
- Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
- validate(candidateAspectClass);
- // 获取切面方法上的注解
- AspectJAnnotation<?> aspectJAnnotation =
- AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
- // 解析出来的注解信息是否为 null
- if (aspectJAnnotation == null) {
- return null;
- }
- // 再次判断是否是切面对象
- if (!isAspect(candidateAspectClass)) {
- throw new AopConfigException("Advice must be declared inside an aspect type:" +
- "Offending method'" + candidateAdviceMethod + "'in class [" +
- candidateAspectClass.getName() + "]");
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Found AspectJ method:" + candidateAdviceMethod);
- }
- AbstractAspectJAdvice springAdvice;
- // 判断标注在方法上的注解类型
- switch (aspectJAnnotation.getAnnotationType()) {
- // 是 PointCut 注解 那么就抛出异常 因为在外面传递进来的方法已经排除了 Pointcut 的方法
- case AtPointcut:
- if (logger.isDebugEnabled()) {
- logger.debug("Processing pointcut'" + candidateAdviceMethod.getName() + "'");
- }
- return null;
- // 环绕通知 构建 AspectJAroundAdvice
- case AtAround:
- springAdvice = new AspectJAroundAdvice(
- candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
- break;
- // 前置通知 构建 AspectJMethodBeforeAdvice
- case AtBefore:
- springAdvice = new AspectJMethodBeforeAdvice(
- candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
- break;
- // 后置通知 AspectJAfterAdvice
- case AtAfter:
- springAdvice = new AspectJAfterAdvice(
- candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
- break;
- // 返回通知 AspectJAfterReturningAdvice
- case AtAfterReturning:
- springAdvice = new AspectJAfterReturningAdvice(
- candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
- AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
- if (StringUtils.hasText(afterReturningAnnotation.returning())) {
- springAdvice.setReturningName(afterReturningAnnotation.returning());
- }
- break;
- // 异常通知 AspectJAfterThrowingAdvice
- case AtAfterThrowing:
- springAdvice = new AspectJAfterThrowingAdvice(
- candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
- AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
- if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
- springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
- }
- break;
- default:
- throw new UnsupportedOperationException(
- "Unsupported advice type on method:" + candidateAdviceMethod);
- }
- // 设置我们构建出来的通知对象的相关属性比如 DeclarationOrder, 在代理调用的时候, 责任链顺序上会用到
- springAdvice.setAspectName(aspectName);
- springAdvice.setDeclarationOrder(declarationOrder);
- String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
- if (argNames != null) {
- springAdvice.setArgumentNamesFromStringArray(argNames);
- }
- springAdvice.calculateArgumentBindings();
- return springAdvice;
- }
至此真正的去获取我们的 Advisor 方法解析完成, List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
3 如果该切面是单实例的就加入到缓存中:
4 遍历所有的切面, 将每个切面的所有的增强器添加在 advisors 中进行返回:
AbstractAutoProxyCreator.shouldSkip()方法中的 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 返回找到的候选的增强器, 然后再调用父类的 shouldSkip()返回 false, 就是不跳过的意思
执行完 shouldSkip()返回到 AbstractAutoProxyCreator.postProcessBeforeInstantiation 的方法, 至此 postProcessBeforeInstantiation 执行完成.
最后 AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 实现了 Bean 的后置处理器 BeanPostProcessor 接口:
该接口有 2 个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization, 其中在 postProcessAfterInitialization 方法主要就是通过前面创建的增强器来创建代理对象
- public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
- if (bean != null) {
- // 获取缓存 key
- Object cacheKey = getCacheKey(bean.getClass(), beanName);
- if (this.earlyProxyReferences.remove(cacheKey) != bean) {
- // 如果有必要就代理
- return wrapIfNecessary(bean, beanName, cacheKey);
- }
- }
- return bean;
- }
进入如果必要就代理方法, wrapIfNecessary(bean, beanName, cacheKey):
- protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
- // 已经被处理过
- if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
- return bean;
- }
- // 不需要增强的
- if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
- return bean;
- }
- // 是不是基础的 bean 是不是需要跳过的
- if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return bean;
- }
- // 如果有匹配的通知, 就创建代理对象
- 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;
- }
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return bean;
- }
1 获取匹配的通知方法, getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null):
- protected Object[] getAdvicesAndAdvisorsForBean(
- Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
- // 找合适的增强器对象
- List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
- // 若为空表示没找到
- if (advisors.isEmpty()) {
- return DO_NOT_PROXY;
- }
- return advisors.toArray();
- }
跟进到找合适的增强器对象方法, findEligibleAdvisors(beanClass, beanName):
- protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
- // 找到 Spring IoC 容器中所有的候选通知
- List<Advisor> candidateAdvisors = findCandidateAdvisors();
- // 判断找到的通知能不能作用到当前的类上
- List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
- extendAdvisors(eligibleAdvisors);
- // 对我们的 advisor 进行排序
- if (!eligibleAdvisors.isEmpty()) {
- eligibleAdvisors = sortAdvisors(eligibleAdvisors);
- }
- return eligibleAdvisors;
- }
跟进到判断找到的通知能不能作用到当前的类上方法, findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName):
- protected List<Advisor> findAdvisorsThatCanApply(
- List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
- ProxyCreationContext.setCurrentProxiedBeanName(beanName);
- try {
- // 从候选的通知器中找到合适正在创建的实例对象的通知器
- return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
- }
- finally {
- ProxyCreationContext.setCurrentProxiedBeanName(null);
- }
- }
跟进到从候选的通知器中找到合适正在创建的实例对象的通知器方法, AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass):
- public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
- // 若候选的增强器集合为空 直接返回
- if (candidateAdvisors.isEmpty()) {
- return candidateAdvisors;
- }
- // 定义一个合适的增强器集合对象
- List<Advisor> eligibleAdvisors = new ArrayList<>();
- // 循环我们候选的增强器对象
- for (Advisor candidate : candidateAdvisors) {
- // 判断我们的增强器对象是不是实现了 IntroductionAdvisor (很明显我们事务的没有实现 所以不会走下面的逻辑)
- if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
- eligibleAdvisors.add(candidate);
- }
- }
- // 不为空
- boolean hasIntroductions = !eligibleAdvisors.isEmpty();
- for (Advisor candidate : candidateAdvisors) {
- // 判断我们的增强器对象是不是实现了 IntroductionAdvisor (很明显我们事务的没有实现 所以不会走下面的逻辑)
- if (candidate instanceof IntroductionAdvisor) {
- // 在上面已经处理过 , 不需要处理
- continue;
- }
- /**
- * 真正的判断增强器是否合适当前类型
- */
- if (canApply(candidate, clazz, hasIntroductions)) {
- eligibleAdvisors.add(candidate);
- }
- }
- return eligibleAdvisors;
- }
跟进到是否能用方法, canApply(candidate, clazz, hasIntroductions):
- public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
- // 判断我们的增强器是否是 IntroductionAdvisor
- if (advisor instanceof IntroductionAdvisor) {
- return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
- }
- // 判断我们事务的增强器 BeanFactoryTransactionAttributeSourceAdvisor 是否实现了 PointcutAdvisor
- else if (advisor instanceof PointcutAdvisor) {
- // 转为 PointcutAdvisor 类型
- PointcutAdvisor pca = (PointcutAdvisor) advisor;
- // 找到真正能用的增强器
- return canApply(pca.getPointcut(), targetClass, hasIntroductions);
- }
- else {
- // It doesn't have a pointcut so we assume it applies.
- return true;
- }
- }
跟进到找到真正能用的增强器方法, canApply(pca.getPointcut(), targetClass, hasIntroductions):
- public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
- Assert.notNull(pc, "Pointcut must not be null");
- if (!pc.getClassFilter().matches(targetClass)) {
- return false;
- }
- /**
- * 通过切点获取到一个方法匹配器对象
- */
- MethodMatcher methodMatcher = pc.getMethodMatcher();
- if (methodMatcher == MethodMatcher.TRUE) {
- // No need to iterate the methods if we're matching any method anyway...
- return true;
- }
- // 判断匹配器是不是 IntroductionAwareMethodMatcher
- IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
- if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
- introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
- }
- // 创建一个集合用于保存 targetClass 的 class 对象
- Set<Class<?>> classes = new LinkedHashSet<>();
- // 判断当前 class 是不是代理的 class 对象
- if (!Proxy.isProxyClass(targetClass)) {
- // 加入到集合中去
- classes.add(ClassUtils.getUserClass(targetClass));
- }
- // 获取到 targetClass 所实现的接口的 class 对象, 然后加入到集合中
- classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
- // 循环所有的 class 对象
- for (Class<?> clazz : classes) {
- // 通过 class 获取到所有的方法
- Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
- // 循环我们的方法
- for (Method method : methods) {
- // 通过 methodMatcher.matches 来匹配我们的方法
- if (introductionAwareMethodMatcher != null ?
- introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
- // 通过方法匹配器进行匹配
- methodMatcher.matches(method, targetClass)) {
- return true;
- }
- }
- }
- return false;
- }
如果该方法返回 true 就表示匹配, 就添加到合适的集合 eligibleAdvisors 中, 遍历完所有的候选增强器后, debug 截图如下:
返回到 AbstractAdvisorAutoProxyCreator.findEligibleAdvisors 方法中, 然后扩展增强器, 如果合适的增强器列表不是空的就排序.
返回到 AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean, 如果空就表示不需要代理, 不为空就表示需要代理.
2 真正创建代理对象, Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)):
- protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
- @Nullable Object[] specificInterceptors, TargetSource targetSource) {
- if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
- AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
- }
- // 创建一个代理对象工厂
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.copyFrom(this);
- // 为 proxyFactory 设置创建 jdk 还是 cglib 代理
- if (!proxyFactory.isProxyTargetClass()) {
- if (shouldProxyTargetClass(beanClass, beanName)) {
- proxyFactory.setProxyTargetClass(true);
- }
- else {
- evaluateProxyInterfaces(beanClass, proxyFactory);
- }
- }
- // 把我们的 specificInterceptors 数组中的 Advisor 转化为数组形式的
- Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
- // 为我们的代理工加入通知器,
- proxyFactory.addAdvisors(advisors);
- // 设置 targetSource 对象
- proxyFactory.setTargetSource(targetSource);
- customizeProxyFactory(proxyFactory);
- proxyFactory.setFrozen(this.freezeProxy);
- if (advisorsPreFiltered()) {
- proxyFactory.setPreFiltered(true);
- }
- // 真正创建代理对象
- return proxyFactory.getProxy(getProxyClassLoader());
- }
跟进到真正创建代理对象方法, proxyFactory.getProxy(getProxyClassLoader()):
- public Object getProxy(@Nullable ClassLoader classLoader) {
- //createAopProxy() 用来创建我们的代理工厂
- return createAopProxy().getProxy(classLoader);
- }
跟进到创建 AOP 代理方法, createAopProxy():
- protected final synchronized AopProxy createAopProxy() {
- if (!this.active) {
- activate();
- }
- return getAopProxyFactory().createAopProxy(this);
- }
跟进到 getAopProxyFactory().createAopProxy(this):
- public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
- // 判断我们是否指定使用 cglib 代理 ProxyTargetClass =true 默认 false
- 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.");
- }
- //targetClass 是接口使用的就是 jdk 代理
- if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
- return new JdkDynamicAopProxy(config);
- }
- //cglib 代理
- return new ObjenesisCglibAopProxy(config);
- }
- else {
- //jdk 动态代理
- return new JdkDynamicAopProxy(config);
- }
- }
跟进到创建动态代理 (注意这个是 jdk 的, cglib 同理) 方法, getProxy(classLoader):
- public Object getProxy(@Nullable ClassLoader classLoader) {
- if (logger.isDebugEnabled()) {
- logger.debug("Creating JDK dynamic proxy: target source is" + this.advised.getTargetSource());
- }
- Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
- findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
- // 创建 jdk 动态代理
- return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
- }
有没有眼前一亮: 该方法用来创建我们的代理对象, 如果 proxyTargetClass = true, 创建 cglib 代理 , 为 false, 如果代理类没有实现接口也创建 cglib 代理, 否则创建 jdk 代理
至此 AnnotationAwareAspectJAutoProxyCreator 创建动态代理完成!!
四, AOP 动态代理 invoke
以 JdkDynamicAopProxy 为例, CGLIB 动态代理参照 Jdk 动态代理自行分析
根据到 JdkDynamicAopProxy 的 invole 方法:
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Object oldProxy = null;
- boolean setProxyContext = false;
- // 获取到我们的目标对象
- TargetSource targetSource = this.advised.targetSource;
- Object target = null;
- try {
- // 若是 equals 方法不需要代理
- if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
- // The target does not implement the equals(Object) method itself.
- return equals(args[0]);
- }
- // 若是 hashCode 方法不需要代理
- else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
- // The target does not implement the hashCode() method itself.
- return hashCode();
- }
- // 若是 DecoratingProxy 也不要拦截器执行
- else if (method.getDeclaringClass() == DecoratingProxy.class) {
- // There is only getDecoratedClass() declared -> dispatch to proxy config.
- return AopProxyUtils.ultimateTargetClass(this.advised);
- }
- else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
- method.getDeclaringClass().isAssignableFrom(Advised.class)) {
- // Service invocations on ProxyConfig with the proxy config...
- return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
- }
- Object retVal;
- /**
- * 这个配置是暴露我们的代理对象到线程变量中, 需要搭配 @EnableAspectJAutoProxy(exposeProxy = true)一起使用
- * 比如在目标对象方法中再次获取代理对象可以使用这个 AopContext.currentProxy()
- * 还有的就是事务方法调用事务方法的时候也是用到这个
- */
- if (this.advised.exposeProxy) {
- // 把我们的代理对象暴露到线程变量中
- oldProxy = AopContext.setCurrentProxy(proxy);
- setProxyContext = true;
- }
- // 获取我们的目标对象
- target = targetSource.getTarget();
- // 获取我们目标对象的 class
- Class<?> targetClass = (target != null ? target.getClass() : null);
- // 把 aop 的 advisor 转化为拦截器链
- List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- // 如果拦截器链为空
- if (chain.isEmpty()) {
- // 通过反射直接调用执行
- Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
- retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
- }
- else {
- // 创建一个方法调用对象
- MethodInvocation invocation =
- new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
- // 调用执行
- retVal = invocation.proceed();
- }
- // Massage return value if necessary.
- Class<?> returnType = method.getReturnType();
- if (retVal != null && retVal == target &&
- returnType != Object.class && returnType.isInstance(proxy) &&
- !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
- // Special case: it returned "this" and the return type of the method
- // is type-compatible. Note that we can't help if the target sets
- // a reference to itself in another returned object.
- retVal = proxy;
- }
- else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
- throw new AopInvocationException(
- "Null return value from advice does not match primitive return type for:" + method);
- }
- return retVal;
- }
- finally {
- if (target != null && !targetSource.isStatic()) {
- // Must have come from TargetSource.
- targetSource.releaseTarget(target);
- }
- if (setProxyContext) {
- // Restore old proxy.
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
跟进到 invocation.proceed()方法, 该方法的调用用到了递归和责任链设计模式:
- public Object proceed() throws Throwable {
- // 从 - 1 开始, 下标 = 拦截器的长度 - 1 的条件满足表示执行到了最后一个拦截器的时候, 此时执行目标方法
- if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
- return invokeJoinpoint();
- }
- // 获取第一个方法拦截器使用的是前 ++
- Object interceptorOrInterceptionAdvice =
- this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
- if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
- // Evaluate dynamic method matcher here: static part will already have
- // been evaluated and found to match.
- InterceptorAndDynamicMethodMatcher dm =
- (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
- if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
- return dm.interceptor.invoke(this);
- }
- else {
- // Dynamic matching failed.
- // Skip this interceptor and invoke the next in the chain.
- return proceed();
- }
- }
- else {
- return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
- }
- }
跟进到 ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this) 方法, 责任链模式, 执行顺序如下:
1 ExposeInvocationInterceptor.invoke 方法:
- public Object invoke(MethodInvocation mi) throws Throwable {
- MethodInvocation oldInvocation = invocation.get();
- invocation.set(mi);
- try {
- return mi.proceed();
- }
- finally {
- invocation.set(oldInvocation);
- }
- }
2 AspectJAfterThrowingAdvice.invoke 方法:
- public Object invoke(MethodInvocation mi) throws Throwable {
- try {
- // 执行下一个通知 / 拦截器
- return mi.proceed();
- }
- catch (Throwable ex) {
- // 抛出异常
- if (shouldInvokeOnThrowing(ex)) {
- // 执行异常通知
- invokeAdviceMethod(getJoinPointMatch(), null, ex);
- }
- throw ex;
- }
- }
3 AfterReturningAdviceInterceptor.invoke 方法:
- public Object invoke(MethodInvocation mi) throws Throwable {
- // 执行下一个通知 / 拦截器
- Object retVal = mi.proceed();
- // 返回通知方法
- this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
- return retVal;
- }
4 AspectJAfterAdvice.invoke 方法:
- public Object invoke(MethodInvocation mi) throws Throwable {
- try {
- // 执行下一个通知 / 拦截器
- return mi.proceed();
- }
- finally {
- // 后置通知的方法总是会被执行 原因就在这 finally
- invokeAdviceMethod(getJoinPointMatch(), null, null);
- }
- }
5 AspectJAroundAdvice.invoke 方法:
- public Object invoke(MethodInvocation mi) throws Throwable {
- if (!(mi instanceof ProxyMethodInvocation)) {
- throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation:" + mi);
- }
- ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
- ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
- JoinPointMatch jpm = getJoinPointMatch(pmi);
- return invokeAdviceMethod(pjp, jpm, null, null);
- }
6 MethodBeforeAdviceInterceptor.invoke 方法:
- public Object invoke(MethodInvocation mi) throws Throwable {
- // 执行前置通知的方法
- this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
- // 执行下一个通知 / 拦截器, 但是该拦截器是最后一个了, 所以会调用目标方法
- return mi.proceed();
- }
运行的执行顺序如下:
总结: 通过 @EnableAspectJAutoProxy 注解开启 AOP 功能, 该注解为我们 Spring 容器中注册了 AnnotationAwareAspectJAutoProxyCreator 组件, AOP 的准备和代理创建都在这个组件中完成, AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor 接口, 在方法 postProcessBeforeInstantiation 中找到 Spring 容器中所有的增强器, 为创建代理做准备; AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口, 在方法 postProcessAfterInitialization 中通过前面找到的候选增强器中找到合适的增强器来创建代理对象, 最后调用目标方法, 进去到代理对象的 invoke 方法中进行调用.
来源: https://www.cnblogs.com/toby-xu/p/11444288.html