往期博客


《Spring源码深度解析 郝佳 第2版》容器的基本实现与XML文件的加载

《Spring源码深度解析 郝佳 第2版》XML标签的解析

《Spring源码深度解析 郝佳 第2版》bean的加载、循环依赖的解决

《Spring源码深度解析 郝佳 第2版》ApplicationContext


1、AOP面向切面编程,是一种思想,不同于OOP,他可以为不具有继承关系的对象引入一个公共行为如日志,安全监测等。具体实现分为两种参考:Spring AOP概念理解 (通俗易懂)先理解几个概念

  1. 通知Advice:也就是需要的功能,如安全、事务、日志等
  2. 切入点Pointcut:目标方法的前、后以及异常处都可以作为切入点
  3. 切面Aspect:就是 Advice + Pointcut,给哪个地方做什么增强
  4. 织入weaving:就是把切面应用到目标对象来创建新的代理对象的过程。Spring AOP或者Aspect AOP实现,区别就是织入时机不同

2、Spring AOP和Aspect AOP的区别

  • Spring AOP:动态代理,运行时生成代理对象。他的方便在于Spring帮助我们完成增强的自动织入,在Java中可以根据接口使用JDK动态代理和Cglib动态代理。由Spring自动为我们完成运行时织入。
  • AspectJ:静态代理,编译时直接修改字节码,AspectJ是一套独立的面向切面编程的解决方案。它基于ASM字节码编辑技术,在不使用Spring的时候也可单独使用,需要导入对应的aspect相应的jar包,然后编写静态增强逻辑之后,
    • 编译时织入:利用ajc编译器替代javac编译器,直接将源文件(java或者aspect文件)编译成class文件并将切面织入进代码。
    • 编译后织入:利用ajc编译器向javac编译期编译后的class文件或jar文件织入切面代码。
    • 加载时织入(LTW):不使用ajc编译器,利用aspectjweaver.jar工具,使用java agent代理在类加载期将切面织入进代码。这和之前的二进制编织完全一样,所不同的是织入会被延后,直到类加载器将类加载到JVM。

Spring AOP 与ApectJ 的目的一致,都是为了统一处理横切业务,但与AspectJ不同的是,Spring AOP并不尝试提供完整的AOP功能(即使它完全可以实现),Spring AOP 更注重的是与Spring IOC容器的结合,并结合该优势来解决横切业务的问题,因此在AOP的功能完善方面,相对来说AspectJ具有更大的优势,同时,Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),因此Spring很机智回避了这点,转向采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ(静态织入)最根本的区别。

在AspectJ1.5后,引入@Aspect形式的注解风格的开发,Spring也非常快地跟进了这种方式,因此Spring 2.0后便使用了与AspectJ一样的注解。请注意,Spring 只是使用了与 AspectJ 5 一样的注解,但仍然没有使用 AspectJ 的编译器,底层依是动态代理技术的实现,因此并不依赖于 AspectJ 的编译器,因此无论是使用spring aop还是 aspectj都需要aspectjweaver.jar spring-aop.jar这两个jar包。使用AspectJ 的 动态织入LTW 还 需要额外的jar包 spring-instrument.jar。

3、在Spring中配置<aop:aspectj-autoproxy>标签之后使用Spring AOP

  • 创建用于拦截的bean
  • 创建Advisor:定义切面@AspectJ,声明切点@Pointcut("execution(* *.xxx(..))"),声明通知@Before@After@Around等注解
  • 创建配置文件:在xml配置文件加上<aop:aspectj-autoproxy> 和待拦截的bean、切面bean
  • 测试

4、在SpringBoot中使用 Spring AOP步骤:https://cloud.tencent.com/developer/article/1690944


目录

  1. <aop:aspectj-autoproxy>标签

    • AopNamespaceHandler的init方法注册AspectJAutoProxyBeanDefinitionParser
    • AspectJAutoProxyBeanDefinitionParser的parse方法注册AnnotationAwareAspectJAutoProxyCreator,并设置target-proxy-class和expose-proxy属性值到BeanDefinition中
  2. AnnotationAwareAspectJAutoProxyCreator解析@AspectJ注解标识的Advisor

    • Spring AOP的时机
    • AbstractAutoProxyCreator核心实现AOP
      • wrapIfNessary方法对目标bean封装,然后调用getAdvicesAndAdvisorForBean查找能用到的advisors
      • ProxyFactory内部封装advisors然后createProxy方法创建代理对象
    • JdkDynamicAopProxy分析
    • Cglib2AopProxy分析
  3. AspectJ AOP


一、<aop:aspectj-autoproxy>标签

只要是声明的自定义注解,一定在需要一个他的解析器,解析器名称一般为XxxNamespaceHandler,在AopNamespaceHandler可以看到 设置对@AspectJ注解的解析器AspectJAutoProxyBeanDefinitionParser

public class AopNamespaceHandler extends NamespaceHandlerSupport {public AopNamespaceHandler() {}public void init() {this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());// 设置对@AspectJ注解的解析器AspectJAutoProxyBeanDefinitionParserthis.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}
}

1.注册AspectJAutoProxyBeanDefinitionParser

所有的解析器都是对BeanDefinitionParser接口的统一实现,入口都是parse()方法,然后调用registerAspectJAnnotationAutoProxyCreatorIfNecessary() 注册 AnnotationAwareAspectJAutoProxyCreator 解析器的beanDefinition用于实现AOP

// AspectJAutoProxyBeanDefinitionParser的parse()方法@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) {// 1. 注册AnnotationAwareAspectJAutoProxyCreatorAopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);// 2. 对于注解类的子类的处理this.extendBeanDefinition(element, parserContext);return null;}private void extendBeanDefinition(Element element, ParserContext parserContext) {BeanDefinition beanDef = parserContext.getRegistry().getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");if (element.hasChildNodes()) {this.addIncludePatterns(element, parserContext, beanDef);}}

2. 注册AnnotationAwareAspectJAutoProxyCreator

// AopNamespaceUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {// 1.1. 注册或者升级 AutoProxyCreator定义beanName为// org.Springframework.aop.configinternalAutoProxyCreator的BeanDefinitionBeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 1.2. 对proxy-target-class以及expose-proxy属性的处理useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);// 1.3. 注册组件并通知,便于监听器做进一步处理registerComponentIfNecessary(beanDefinition, parserContext);}
// 2.1 真正注册AnnotationAwareAspectJAutoProxyCreator
// AopConfigUtils
@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {// 对beanDefinition进行注册或者升级return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}
// AopConfigUtils@Nullableprivate static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");// 容器中已经存在自动代理创建器,需要根据优先级选择一个if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;} else {// 容器中还不存在自动代理创建器,注册对应的beanDefinitionRootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", -2147483648);beanDefinition.setRole(2);registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);return beanDefinition;}}
// 2.2. 对proxy-target-class以及expose-proxy属性设置到BeanDefinition

在xml配置文件中对<aop:aspectj-autoproxy proxy-target-class = "true" expose-proxy = "true">或者<aop:config proxy-target-class = "true" expose-proxy = "true"> ... <aop:config> ,此处就是解析并给beanDefinition设置两个属性

  • proxy-target-class:默认Spring AOP使用JDK动态代理,给此属性设置为true表示强制使用Cglib动态代理,需要注意使用Cglib时候不能对final修饰的类代理和需要将Cglib的二进制包放在classpath下面
  • expose-proxy:主要是暴露动态代理上下文AopContext,使用AopContext.currentProxy()获得当前代理,以便解决同类内调用方法不走代理的情况(具体事例就是@Transcation注解使用时的一种情况)
// AopNamespaceUtilsprivate static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {if (sourceElement != null) {boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute("proxy-target-class"));if (proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute("expose-proxy"));if (exposeProxy) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}
// AopConfigUtils
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);}}public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);}}

二、AnnotationAwareAspectJAutoProxyCreator解析@AspectJ

1. Spring AOP的时机

// 不存在循环依赖AOP的时机postProcessAfterInitialization()

AnnotationAwareAspectJAutoProxyCreator实现AbstractAutoProxyCreatorlei完成AOP的核心功能。

他实现BeanProcessor接口,因此无循环依赖的情况下对Bean的具体AOP的逻辑在父类AbstractAutoProxyCreator的postProcessAfterInitalization()方法中

// 存在循环依赖AOP时机getEarlyBeanReference()

首先需要明白解决单例bean循环依赖的关键就是在三级缓存中暴露ObjectFactory

addSingletonFactory(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}
});

有循环依赖的情况并且A不需要AOP增强的情况,如A和B互相依赖,并且都是单例的,会使用三级缓存解决循环依赖,大致过程

  1. A在实例化完成之后会进行属性填充,此时会将ObjectFactory放到三级缓存,然后进行populateBean()、initializationBean()、postProcessAfterInitialization()等。

  2. A在populateBean()时发现A依赖B,就会转去B的getBean()…然后就是B的一系列流程…直到B需要populateBean()的时候发现需要A,会从三级缓存中的ObjectFactory实际调用AbstractAutoProxyCreator重写的getEarlyBeanReference()拿到半实例的A,假如A不需要AOP,那么完全没问题在getEarlyBeanReference()直接返回A即可,B此时就会拿到半实例不需要增强的A完成初始化,然后初始化好的B被移动到一级缓存

  3. 然后转回A的populateBean(),在一级缓存中拿到初始化好的B,然后完成后续初始化。

但是有循环依赖并且A需要AOP增强的时候,发挥关键的就是暴露在三级缓存中的getEarlyBeanReference()了。

  1. 主要逻辑在AbstractAutoProxyCreator重写的getEarlyBeanReference(),当B需要从三级缓存中拿到半实例的A时候,这个时候getEarlyBeanReference()就会被调用,会判断A是否需要增强。

  2. 当A需要增强,此时B需要填充A增强的代理对象,那么AOP的时机不能像往常一样放到postProcessAfterInitiallization()中了,而是在这里直接进行AOP返回给B的是A的增强代理实例,然后放到earlyProxyReferences, 标记这个bean已经被early处理过了,避免在postProcessAfterInitiallization()中重复处理

回顾往期博客《Spring源码深度解析 郝佳 第2版》bean的加载、循环依赖的解决,会发现如果B想要从三级缓存拿到代理的A,会调用getEarlyBeanReference()会进入SmartInstantiantionAwareBeanPostProcess的getEarlyBeanReference(),然后返回exposedObject并移动到二级缓存。就是在这里完成的提前AOP。

而看关键SmartInstantiationAwareBeanPostProcess的getEarlyBeanReference()核心实现

// SmartInstantiationAwareBeanPostProcess是一个接口,默认方法实现
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}
// 查看他的实现类,发现真正的方法在AbstractAutoProxyCreator类重写实现
// AbstractAutoProxyCreator
public Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = this.getCacheKey(bean.getClass(), beanName);this.earlyProxyReferences.put(cacheKey, bean);return this.wrapIfNecessary(bean, beanName, cacheKey);}

于是有转到和AbstractAutoProxyCreator类

2. AbstractAutoProxyCreator核心类实现AOP

// 提前AOP的情况

private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap(16);// 主要是循环依赖下的AOP解决// aop相关的代理,相当于会把bean替换成一个代理类。那看下循环依赖的时候怎么处理// 主要逻辑在AbstractAutoProxyCreator中
// 实现了getEarlyBeanReference,会在这里直接返回一个代理类
// 然后放到earlyProxyReferences, 标记这个bean已经被early处理过了
//
public Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = this.getCacheKey(bean.getClass(), beanName);this.earlyProxyReferences.put(cacheKey, bean);return this.wrapIfNecessary(bean, beanName, cacheKey);}

// 正常AOP的情况

 @Nullableprivate BeanFactory beanFactory; // 成员变量private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap(256); // 记录那些bean需要增强// AbstractAutoProxyCreator重写了BeanPostProcessor的postProcessAfterInitialization()等方法public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {// 1. 根据给定的class和beanName构造一个key,格式beanClassName_beanNameObject cacheKey = this.getCacheKey(bean.getClass(), beanName);// 主要处理循环依赖情况下提前AOP和现在和AOP重复if (this.earlyProxyReferences.remove(cacheKey) != bean) {// 2. 适合被代理,需要封装成指定beanreturn this.wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

// 2. wrapIfNecessary

如果适合被代理,需要封装成指定bean,放到adviserBeans

// AbstractAutoProxyCreator
//  适合被代理,需要封装成指定bean
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 已经处理过了if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;} // 无需增强else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;} // 基础设施类和指定的类跳过不增强// 需要增强的类else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {// 2.1 如果存在增强方法需要创建代理,如@AspectJ注解配置的切面、通知Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 2.2 增强方法不为空,需要创建代理执行增强方法Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;} else {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}} else {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}}
// 2.1 getAdvicesAndAdvisorsForBean

解析增强方法,如@AspectJ注解配置的切面、通知,然后找到该bean能运用的增强

  • // 找出所有的增强方法放到List
  • // 找出针对该bean的增强方法放到List
// AbstractAutoProxyCreator
// 模板方法,由子类AbstractAdvisorAutoProxyCreator 重写@Nullableprotected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> var1, String var2, @Nullable TargetSource var3) throws BeansException;// AbstractAdvisorAutoProxyCreator @Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {// 调用 findEligibleAdvisorsList<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();}
// AbstractAdvisorAutoProxyCreator的findEligibleAdvisors查找所有增强方法或者增强器protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 2.1.1查找所有的增强方法,因为分析的使用注解@AspectJ配置的AOP,// 因此查找方法其实是子类AnnotationAwareAspectJAutoProxyCreator类List<Advisor> candidateAdvisors = this.findCandidateAdvisors();// 2.1.2针对该bean的增强方法List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);this.extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
// 2.1.1查找所有的增强方法,因为分析的使用注解@AspectJ配置的AOP, 因此查找方法其实是子类AnnotationAwareAspectJAutoProxyCreator类
// AbstractAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");return this.advisorRetrievalHelper.findAdvisorBeans();}// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {// 父类查找List<Advisor> advisors = super.findCandidateAdvisors();if (this.aspectJAdvisorsBuilder != null) {// 核心实现 BeanFactoryAspectJAdvisorsBuilderadvisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}

// 核心实现 BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()

  1. 获取所有注册在beanFactory的beanName
  2. 遍历所有beanName,找出@AspectJ标注的类,然后 就是最复杂的地方,委托给AspectJAdvisorFactory接口的实现类ReflectiveAspectJAdvisorFactory的getAdvisors方法
  3. 对于切面类增强方法提取
  4. 将提取结果加入缓存
// BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {List<String> aspectNames = this.aspectBeanNames;if (aspectNames == null) {synchronized(this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new ArrayList();List<String> aspectNames = new ArrayList();String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);String[] var18 = beanNames;int var19 = beanNames.length;for(int var7 = 0; var7 < var19; ++var7) {String beanName = var18[var7];if (this.isEligibleBean(beanName)) {Class<?> beanType = this.beanFactory.getType(beanName, false);// 对标注@AspectJ的切面解析if (beanType != null && this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);// 最复杂的地方,委托给AspectJAdvisorFactory接口的实现类ReflectiveAspectJAdvisorFactory的getAdvisors方法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 {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();} else {List<Advisor> advisors = new ArrayList();Iterator var3 = aspectNames.iterator();while(var3.hasNext()) {String aspectName = (String)var3.next();List<Advisor> cachedAdvisors = (List)this.advisorsCache.get(aspectName);if (cachedAdvisors != null) {advisors.addAll(cachedAdvisors);} else {MetadataAwareAspectInstanceFactory factory = (MetadataAwareAspectInstanceFactory)this.aspectFactoryCache.get(aspectName);advisors.addAll(this.advisorFactory.getAdvisors(factory));}}return advisors;}}

// 获取切面的增强方法是最复杂的地方,委托给AspectJAdvisorFactory接口的实现类ReflectiveAspectJAdvisorFactory的getAdvisors方法

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {// 标记为@AspectJ的切面类Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();this.validate(aspectClass);MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);List<Advisor> advisors = new ArrayList();// 1.  获取切面每个方法Iterator var6 = this.getAdvisorMethods(aspectClass).iterator();while(var6.hasNext()) {Method method = (Method)var6.next();// 2.  对每个方法解析Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);if (advisor != null) {advisors.add(advisor);}}if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);// 3.  配置了增强延迟初始化,需要在在首部加上同步增强实例化加载器advisors.add(0, instantiationAdvisor);}Field[] var12 = aspectClass.getDeclaredFields();int var13 = var12.length;for(int var14 = 0; var14 < var13; ++var14) {Field field = var12[var14];Advisor advisor = this.getDeclareParentsAdvisor(field);if (advisor != null) {advisors.add(advisor);}}return advisors;}
// 1. 获取切面每个方法
private List<Method> getAdvisorMethods(Class<?> aspectClass) {List<Method> methods = new ArrayList();ReflectionUtils.doWithMethods(aspectClass, (method) -> {if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {methods.add(method);}}, ReflectionUtils.USER_DECLARED_METHODS);if (methods.size() > 1) {methods.sort(METHOD_COMPARATOR);}return methods;}// 2. 调用解析每个方法以及增强注解@Nullablepublic Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());// 2.1  解析PointCut切点AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());// 切点表达式封装为 InstantiationModelAwarePointcutAdvisorImplreturn expressionPointcut == null ? null : new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}// 2.1 解析PointCut切点表达式,封装到 InstantiationModelAwarePointcutAdvisorImpl
@Nullableprivate AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;} else {AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);ajexp.setExpression(aspectJAnnotation.getPointcutExpression());if (this.beanFactory != null) {ajexp.setBeanFactory(this.beanFactory);}return ajexp;}}// 2.2. 调用解析每个方法以及增强注解
@Nullablepublic Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();this.validate(candidateAspectClass);// 获取方法上的注解AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;} else if (!this.isAspect(candidateAspectClass)) {throw new AopConfigException("Advice must be declared inside an aspect type: Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]");} else {if (this.logger.isDebugEnabled()) {this.logger.debug("Found AspectJ method: " + candidateAdviceMethod);}Object springAdvice;// 根据注解类型解析switch(aspectJAnnotation.getAnnotationType()) {// Pointcut切点不解析case AtPointcut:if (this.logger.isDebugEnabled()) {this.logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;case AtAround:springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtBefore:springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfter:springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfterReturning:springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning)aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {((AbstractAspectJAdvice)springAdvice).setReturningName(afterReturningAnnotation.returning());}break;case AtAfterThrowing:springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {((AbstractAspectJAdvice)springAdvice).setThrowingName(afterThrowingAnnotation.throwing());}break;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}((AbstractAspectJAdvice)springAdvice).setAspectName(aspectName);((AbstractAspectJAdvice)springAdvice).setDeclarationOrder(declarationOrder);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {((AbstractAspectJAdvice)springAdvice).setArgumentNamesFromStringArray(argNames);}((AbstractAspectJAdvice)springAdvice).calculateArgumentBindings();return (Advice)springAdvice;}}

可以看出Spring会对不同注解的方法生成不同的增强器如AspectJAroundAdvice、AspectJAfterReturningAdvice等

以@Before注解为例
  • 在拦截链中放置MethodBeforeAdviceInterceptor ,MethodBeforeAdviceInterceptor 完成了增强逻辑
  • 在MethodBeforeAdviceInterceptor 放置AspectJMethodBeforeAdvice
  • 在调用invoke方法的时候串联调用,// 调用AspectJMethodBeforeAdvice的前置增强方法然后才是 // 方法执行
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {private final MethodBeforeAdvice advice;public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}// @Before注解增强逻辑public Object invoke(MethodInvocation mi) throws Throwable {// 调用AspectJMethodBeforeAdvice的方法前置增强this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());// 方法执行return mi.proceed();}
}
// AspectJMethodBeforeAdvicepublic void before(Method method, Object[] args, @Nullable Object target) throws Throwable {// 激活增强方法this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);}
// AbstractAspectJAdvice
protected Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) throws Throwable {// 重载return this.invokeAdviceMethodWithGivenArgs(this.argBinding(this.getJoinPoint(), jpMatch, returnValue, ex));}
// AbstractAspectJAdviceprotected transient Method aspectJAdviceMethod; // 正是对前置增强的方法protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {Object[] actualArgs = args;if (this.aspectJAdviceMethod.getParameterCount() == 0) {actualArgs = null;}try {ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);// 真正激活,调用的Method的invokereturn this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);} catch (IllegalArgumentException var4) {throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", var4);} catch (InvocationTargetException var5) {throw var5.getTargetException();}}
以@After注解为例

和前置不同,直接在拦截器链中使用了中间的AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {super(aspectJBeforeAdviceMethod, pointcut, aif);}public Object invoke(MethodInvocation mi) throws Throwable {Object var2;try {var2 = mi.proceed();} finally {// 激活增强方法this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);}return var2;}public boolean isBeforeAdvice() {return false;}public boolean isAfterAdvice() {return true;}
}
// 2.1.2 findAdvisorsThatCanApply

之前找到所有的增强之后封装为XxxAdvice,然后就是遍历找出该bean能运用的放到List集合

protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);List var4;try {// 委托var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);} finally {ProxyCreationContext.setCurrentProxiedBeanName((String)null);}return var4;}// AopUtilspublic static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;} else {List<Advisor> eligibleAdvisors = new ArrayList();Iterator var3 = candidateAdvisors.iterator();while(var3.hasNext()) {Advisor candidate = (Advisor)var3.next();// 引介增强if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();Iterator var7 = candidateAdvisors.iterator();while(var7.hasNext()) {Advisor candidate = (Advisor)var7.next();// 普通bean的增强if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}}
// canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor)advisor).getClassFilter().matches(targetClass);} else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor)advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);} else {return true;}}
// 2.2 ProxyFactory内部封装advisors然后createProxy创建代理

如果可以运用的增强方法不为空,需要为该bean创建代理执行增强方法,

// 2.2.1 设置beanDefinition原来的属性

// 2.2.2 实例化proxyFactory ,内部封装了getProxy等方法,需要根据下面的配置进去的属性获取代理对象

// 2.2.3 获取当前bean的属性

// 2.2.4 设置属性,根据我们配置的proxy-target-class属性,选用JDK还是Cglib动态代理时需要用到保存在ProxyFactory中的该属性

// 2.2.5 加入能用的增强器,复杂

// 2.2.6 设置被代理类

// 2.2.7 定制代理

// 2.2.8 委托ProxyFactory获取代理对象,复杂

// AbstractAutoProxyCreator protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {// 2.2.1 设置beanDefinition原来的属性if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);}// 2.2.2 实例化proxyFactory 封装了getProxy等方法,需要根据下面的配置进去的属性获取代理对象ProxyFactory proxyFactory = new ProxyFactory();// 2.2.3 获取当前bean的属性proxyFactory.copyFrom(this);// 2.2.4 设置属性,根据我们配置的proxy-target-class属性if (!proxyFactory.isProxyTargetClass()) {if (this.shouldProxyTargetClass(beanClass, beanName)) {// Cglib动态代理proxyFactory.setProxyTargetClass(true);} else {// JDK动态代理this.evaluateProxyInterfaces(beanClass, proxyFactory);}}// 2.2.5 加入能用的增强器Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);// 2.2.6 设置被代理类proxyFactory.setTargetSource(targetSource);// 2.2.7 定制代理this.customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (this.advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 2.2.8 委托ProxyFactory获取代理对象return proxyFactory.getProxy(this.getProxyClassLoader());}
// 2.2.5 buildAdvisors封装能用的增强器

因为Spring涉及了过多的拦截器、增强器、增强方法等方式对逻辑进行增强,所以非常有必要封装成为Advisor来进行代理的创建

简单来说:Advice 是通知,Advisor 是增强器。使用 spring aop 要定义切面,切面里面有 通知 和 切点。

在项目启动的过程中,项目中的所有切面会被 AnnotationAwareAspectJAutoProxyCreator 解析,它会找到切面中的每一个通知以及通知对应的切点,拿这二者构建一个新的对象,这个对象就是 Advisor。最后将所有解析得到的增强器注入到容器中。

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {Advisor[] commonInterceptors = this.resolveInterceptorNames();List<Object> allInterceptors = new ArrayList();if (specificInterceptors != null) {allInterceptors.addAll(Arrays.asList(specificInterceptors));if (commonInterceptors.length > 0) {if (this.applyCommonInterceptorsFirst) {allInterceptors.addAll(0, Arrays.asList(commonInterceptors));} else {allInterceptors.addAll(Arrays.asList(commonInterceptors));}}}int i;if (this.logger.isTraceEnabled()) {int nrOfCommonInterceptors = commonInterceptors.length;i = specificInterceptors != null ? specificInterceptors.length : 0;this.logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + i + " specific interceptors");}Advisor[] advisors = new Advisor[allInterceptors.size()];for(i = 0; i < allInterceptors.size(); ++i) {// 封装advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));}return advisors;}
//DefaultAdvisorAdapterRegistrypublic Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {if (adviceObject instanceof Advisor) {return (Advisor)adviceObject;} else if (!(adviceObject instanceof Advice)) {throw new UnknownAdviceTypeException(adviceObject);} else {Advice advice = (Advice)adviceObject;if (advice instanceof MethodInterceptor) {// MethodInterceptor 类型使用 DefaultPointcutAdvisor封装return new DefaultPointcutAdvisor(advice);} else {Iterator var3 = this.adapters.iterator();AdvisorAdapter adapter;// 存在 AdvisorAdapter 也需要封装 DefaultPointcutAdvisordo {if (!var3.hasNext()) {throw new UnknownAdviceTypeException(advice);}adapter = (AdvisorAdapter)var3.next();} while(!adapter.supportsAdvice(advice));return new DefaultPointcutAdvisor(advice);}}}
// 2.2.8 委托ProxyFactory获取代理对象
// ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {return this.createAopProxy().getProxy(classLoader);}
// ProxyCreatorSupportprotected final synchronized AopProxy createAopProxy() {if (!this.active) {this.activate();}// 委托AopProxyFactory接口的createProxy()return this.getAopProxyFactory().createAopProxy(this);}
// DefaultAopProxyFactory 实现AopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {return new JdkDynamicAopProxy(config);} else {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.");} else {// 选用Cglib还是JDK动态代理return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));}}}

在分析JDK动态代理和Cglib动态代理之前,先看看如何使用

  1. 使用JDK动态代理:需要被代理类实现某个接口

    • 创建处理器MyInvocationHandler实现InvocationHandler接口,重写invoke、getProxy()方法(也可以放到外面直接Proxy.newProxyInstance()获得代理对象),然后构造方法传入被代理对象
    • 创建被代理对象实例,传入MyInvocationHandler实例
    • 通过MyInvocationHandler.getProxy()获得代理对象proxy
    • 测试 proxy.test()
  2. 使用Cglib动态代理:要求被代理类不能被final修饰
    • 创建处理器MyMethodInterceptor实现MethodInterceptor,重写intercepter()方法
    • 测试,创建Enhancer实例
      • 调用setSuperClass()设置被代理类Class,
      • 调用setCallback()传入MyMethodInterceptor实例,
      • 调用create()方法创建代理对象,然后调用方法test()

// 3. JdkDynamicAopProxy处理器分析

可以看到// final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable 它也实现 InvocationHandler

关键点就是invoke、getProxy方法

  public Object getProxy() {return this.getProxy(ClassUtils.getDefaultClassLoader());}public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}

invoke方法主要是创建了一个拦截器链,然后使用ReflectiveMethodInvocation封装,在他的proceed()方法实现拦截器的逐一调用

 @Nullablepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Object target = null;Object retVal;try {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {Boolean var18 = this.equals(args[0]);return var18;}if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {Integer var17 = this.hashCode();return var17;}if (method.getDeclaringClass() == DecoratingProxy.class) {Class var16 = AopProxyUtils.ultimateTargetClass(this.advised);return var16;}if (this.advised.opaque || !method.getDeclaringClass().isInterface() || !method.getDeclaringClass().isAssignableFrom(Advised.class)) {// 自身类.class.isAssignableFrom(自身类或者子类.class) 返回true,其他情况返回falseif (this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();Class<?> targetClass = target != null ? target.getClass() : null;// 拦截器链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();}Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {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);}Object var12 = retVal;return var12;}retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);} finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {AopContext.setCurrentProxy(oldProxy);}}return retVal;}// ReflectiveMethodInvocation@Nullablepublic Object proceed() throws Throwable {if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {// 切点return this.invokeJoinpoint();} else {// 拦截器链Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();} else {return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);}}}

// 4. Cglib2AopProxy处理器分析

首先需要导入依赖

<dependency><groupId>springframework</groupId><artifactId>spring-aop</artifactId><version>1.2.5</version>
</dependency>

getProxy方法

public Object getProxy() {return this.getProxy((ClassLoader)null);}public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {Class targetClass = this.advised.getTargetSource().getTargetClass();logger.debug("Creating CGLIB2 proxy" + (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));}Enhancer enhancer = new Enhancer();try {Class rootClass = this.advised.getTargetSource().getTargetClass();Class proxySuperClass = AopUtils.isCglibProxyClass(rootClass) ? rootClass.getSuperclass() : rootClass;this.validateClassIfNecessary(proxySuperClass);enhancer.setSuperclass(proxySuperClass);enhancer.setCallbackFilter(new Cglib2AopProxy.ProxyCallbackFilter(this.advised));enhancer.setStrategy(new UndeclaredThrowableStrategy(class$java$lang$reflect$UndeclaredThrowableException == null ? (class$java$lang$reflect$UndeclaredThrowableException = class$("java.lang.reflect.UndeclaredThrowableException")) : class$java$lang$reflect$UndeclaredThrowableException));enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));Callback[] callbacks = this.getCallbacks(rootClass);enhancer.setCallbacks(callbacks);if (Cglib2AopProxy.CglibUtils.canSkipConstructorInterception()) {enhancer.setInterceptDuringConstruction(false);}Class[] types = new Class[callbacks.length];for(int x = 0; x < types.length; ++x) {types[x] = callbacks[x].getClass();}enhancer.setCallbackTypes(types);Object proxy;if (this.constructorArgs != null) {proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);} else {proxy = enhancer.create();}return proxy;} catch (CodeGenerationException var8) {throw new AspectException("Couldn't generate CGLIB subclass of class '" + this.advised.getTargetSource().getTargetClass() + "': " + "Common causes of this problem include using a final class or a non-visible class", var8);} catch (IllegalArgumentException var9) {throw new AspectException("Couldn't generate CGLIB subclass of class '" + this.advised.getTargetSource().getTargetClass() + "': " + "Common causes of this problem include using a final class or a non-visible class", var9);} catch (Exception var10) {throw new AspectException("Unexpected AOP exception", var10);}}

intercepter方法

private class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private DynamicAdvisedInterceptor() {}public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {MethodInvocation invocation = null;Object oldProxy = null;boolean setProxyContext = false;Class targetClass = null;Object target = null;Object var12;try {Object retVal = null;if (Cglib2AopProxy.this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = this.getTarget();if (target != null) {targetClass = target.getClass();}List chain = Cglib2AopProxy.this.advised.getAdvisorChainFactory().getInterceptorsAndDynamicInterceptionAdvice(Cglib2AopProxy.this.advised, proxy, method, targetClass);if (chain.isEmpty()) {retVal = methodProxy.invoke(target, args);} else {invocation = new Cglib2AopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);retVal = invocation.proceed();}retVal = Cglib2AopProxy.massageReturnTypeIfNecessary(proxy, target, retVal);var12 = retVal;} finally {if (target != null) {this.releaseTarget(target);}if (setProxyContext) {AopContext.setCurrentProxy(oldProxy);}}return var12;}public int hashCode() {return Cglib2AopProxy.this.advised.hashCode();}protected Object getTarget() throws Exception {return Cglib2AopProxy.this.advised.getTargetSource().getTarget();}protected void releaseTarget(Object target) throws Exception {Cglib2AopProxy.this.advised.getTargetSource().releaseTarget(target);}}

三、AspectJ动态织入

AspectJ 的底层技术是 静态代理 ,主要是在虚拟机启动的时候通过改变目标对象字节码的方式来完成对目标对象的增强,它比动态代理有更高的效率,因为在动态代理调用过程中,还需要一个动态创建代理类并代理目标对象的步骤,而静态代理是在启动时完成了字节码增强,当系统调用目标类和正常的类无差别,所以效率上会相对高一些。

Aspect是实现AOP编程的一种具体实现

  • 编译时织入,利用ajc编译器替代javac编译器,直接将源文件(java或者aspect文件)编译成class文件并将切面织入进代码。
  • 编译后织入,利用ajc编译器向javac编译期编译后的class文件或jar文件织入切面代码。
  • 加载时织入(LTW),不使用ajc编译器,利用aspectjweaver.jar工具,使用java agent代理在类加载期将切面织入进代码。

前两种织入方法都依赖于ajc的编译工具,LTW却通过java agent机制在内存中操作类文件,可以不需要ajc的支持做到 动态织入

不过,这里有一个挺有意思的问题,我们知道编译期一定会编译AnnoAspect类,那么这时候通过切面语法我们就可以找到他要处理的App类,这大概就是编译阶段织入的大概流程。

但是如果在类加载期处理的话,当类加载到App类的时候,我们并不知道这个类需要被AnnoAspect处理。。。因此为了实现LTW,我们肯定要有个配置文件,来告诉类加载器,某某某切面需要优先考虑,他们很可能会影响其他的类。为了实现LTW,我们需要在资源目录下配置META-INF/aop.xml文件,来告知类加载器我们当前注册的切面。

比如说Load-Time Weaving的方式 还 需要额外的jar包 spring-instrument.jar。
当然,无论是使用spring aop还是 aspectj都需要aspectjweaver.jar spring-aop.jar这两个jar包。

参考:https://blog.csdn.net/whatigame/article/details/103173308

使用步骤

  • 在xml配置文件中加上<aop:aspect-autoproxy><context:load-time-weaver>开启Load-Time Weaving开关
  • 在class路径下新建META-INF文件夹,文件夹创建aop.xml文件,里面配置<aspect>、 <weaver>、<aspects>主要是告诉AspectJ哪些包进行织入,并使用哪些增强器
  • 加入启动参数,也就是应用指定的jar包
  • 测试

《Spring源码深度解析 郝佳 第2版》AOP相关推荐

  1. 《Spring源码深度解析 郝佳 第2版》ApplicationContext

    往期博客: <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 <Spring源码深度 ...

  2. 《Spring源码深度解析 郝佳 第2版》SpringBoot体系分析、Starter的原理

    往期博客 <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 <Spring源码深度解 ...

  3. 《Spring源码深度解析 郝佳 第2版》事务

    往期博客 <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 <Spring源码深度解 ...

  4. 《Spring源码深度解析 郝佳 第2版》JDBC、MyBatis原理

    往期博客 <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 <Spring源码深度解 ...

  5. 《Spring源码深度解析 郝佳 第2版》XML标签的解析

    目录 往期博客<Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 分析了xml文件的加载,接下来就是标签的解析,入口函数有两个 默认标签的解析 自定义标签的解析 一 ...

  6. 《Spring源码深度解析 郝佳 第2版》bean的加载、循环依赖的解决

    往期博客: <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 往期博客完成了xml文件加载 ...

  7. 《Spring源码深度解析 郝佳 第2版》容器的基本实现与XML文件的加载

    目录 Spring的整体架构 容器的基本实现与XML文件的加载 一.Spring的整体架构 Spring是一个分层架构,主要包含以下部分 Core Container Data Access Web ...

  8. Spring源码深度解析(郝佳)-学习-源码解析-基于注解bean定义(一)

    我们在之前的博客 Spring源码深度解析(郝佳)-学习-ASM 类字节码解析 简单的对字节码结构进行了分析,今天我们站在前面的基础上对Spring中类注解的读取,并创建BeanDefinition做 ...

  9. Spring源码深度解析(郝佳)-学习-源码解析-创建AOP静态代理实现(八)

    继上一篇博客,我们继续来分析下面示例的 Spring 静态代理源码实现. 静态 AOP使用示例 加载时织入(Load -Time WEaving,LTW) 指的是在虚拟机载入字节码时动态织入 Aspe ...

最新文章

  1. HDU 2564 词组缩写
  2. 赣南师范大学c语言实验报告,赣南师范大学651C语言程序设计科目三考研真题详解...
  3. Even for transaction data request, metadata is still needed as prerequisite
  4. python多线程没用_Python中的多线程cv2.imshow()不起作用
  5. Android save pictrue by SQLiteOpenHelper
  6. HADOOP:Current usage: 399.9 MB of 1 GB physical memory used; 2.5 GB of 2.1 GB virtual memory used.
  7. 23种设计模式(十二)对象性能之享元模式
  8. 深入探索Java泛型
  9. css集合——好看的按钮样式+阴影+渐变
  10. 黑苹果 10.14.6 安装记录
  11. 蓝桥杯算法训练VIP-调和数列问题
  12. 切尔诺贝利_切尔诺贝利泰坦尼克号的自然恢复历史以及复杂系统的课程
  13. cocos2dx面试题整理
  14. ERROR ITMS-90096
  15. java 对象查找_Java如何从数组中查找对象元素?
  16. springcloud微服务项目解析与服务拆分
  17. windows文件读取 xxe_XXE任意文件读取(当xml解析内容有输出时)
  18. 高等代数_第6章:二次型·矩阵的合同
  19. 带教师端和家长端微信小程序的智慧校园平台源码
  20. 造数神器 python-faker

热门文章

  1. IOC和DI入门案例
  2. rk3399-7.1 MediaPlayer播放在线mp3失败
  3. scratch编程超炫酷时钟
  4. 牛客小白月赛6 J 洋灰三角 数学
  5. Unity学习笔记:2D游戏精灵碰撞互动效果
  6. Python 洛谷 p1104 生日
  7. 【工程光学】光学系统的光束限制
  8. 全志A20平台实现VGA和HDMI双屏同显
  9. 8月1日云栖精选夜读:独家:阿里巴巴DevOps落地实践玩法及思路解析
  10. linux 下PDF文档的压缩