• Spring AOP 详解及@Trasactional


    Spring AOP 详解

    AOP基础

    AOP: Aspect Oriented Program, 面向切面编程。解耦(组织结构调整)、增强(扩展)。

    AOP术语

    术语

    说明

    Aspect(切面

    横切于系统的连接点实现特定功能的类

    JoinPoint(连接点)

    系统执行的某个动态阶段,如对象操作、方法调用等

    Pointcut(切点)

    定义了Aspect发生作用的切入特征

    Advice(增强)

    在连接点执行的增强操作

    Target Object(目标对象)

    Advice作用对象、被增强对象

    Proxy(代理)

    为了实施增强,动态创建的对象。

    Weaving(织入)

    构建可以针对目标对象实施增强行为的代理对象的基础过程。

    AOP Aliance

    AOP Aliance: AOP联盟,定义了AOP的基础规范。

    AOP JavaAPIDoc 网址: Generated Documentation (Untitled)

    AOP 官方白皮书地址:https://aopalliance.sourceforge.net/white_paper/white_paper.pdf

    图1 Spring AOP中的AOP Aliance 基本接口

    AspectJ

    AsprctJ 是Java社区里最完整最流行的AOP框架。

    官网: AspectJ Documentation | The Eclipse Foundation

    AspectJ提供了完整的AOP解决方案,支持以下三种织入时机:

    • compile-time:编译期织入,编译出包含织入代码的 .class 文件
    • post-compile:编译后织入,增强已经编译出来的类,如我们要增强依赖的 jar 包中的某个类的某个方法
    • load-time:在 JVM 进行类加载的时候进行织入

    Spring AOP 和 AspectJ

    Spring AOP: 为Spring IoC上提供的AOP实现,应用于Spring Bean容器管理的,以及Spring 框架其他技术,如Spring Transactional

    AspectJ: 提供完整的AOP解决方案。它比Spring AOP更强大,但也更复杂。还值得注意的是,AspectJ可以应用于所有域对象。

    Spring AOP

    AspectJ

    用纯Java实现

    使用Java编程语言的扩展实现

    无需单独的编译过程

    除非设置了LTW,否则需要AspectJ编译器(ajc)

    仅需运行时编织

    运行时编织不可用。支持编译时,后编译和加载时编织

    不足–仅支持方法级编织

    更强大–可以编织字段,方法,构造函数,静态初始值设定项,最终类/方法等…

    只能在Spring容器管理的bean上实现

    可以在所有领域对象上实施

    仅支持方法执行切入点

    支持所有切入点

    代理是针对目标对象创建的,并且方面已应用于这些代理

    在应用程序执行之前(运行时之前)将方面直接编织到代码中

    比AspectJ慢得多

    更好的性能

    易于学习和应用

    比Spring AOP复杂得多

    Spring AOP代理的生成

    Cglib代理和JDK动态代理。

    JDK 动态代理是JDK内置的动态代理工具,底层原理是反射机制,为目标接口创建代理,动态代理类需要实现InvocationHandler接口。代理实现原理是通过实现被代理类的接口,被代理对象由InvocationHandler进行包装调用。

    public interface InvocationHandler {

       /**

         * @param proxy 包装的代理对象

         * @param method 调用的方法

         * @param args 调用方法参数

        */

        public Object invoke(Object proxy, Method method, Object[] args)

            throws Throwable;

    }

    public static T getProxyObject(T object,

                                   InvocationHandler h) {

    return (T) Proxy.newProxyInstance(object.getClass().getClassLoader(),

                            object.getClass().getInterfaces(), h);

    }

    try {

        super.h.invoke(this, m3, (Object[])null);

    } catch (RuntimeException | Error var2) {

        throw var2;

    } catch (Throwable var3) {

        throw new UndeclaredThrowableException(var3);

    }

    Cglib底层原理通过字节码处理框架ASM修改类的字节码生成继承方法的子类,通过修改字节码生成子类代理直接代替实体类,需要实现MethodInterceptor接口。 继承方式意味着不能对final修饰的类、final修饰的方法、私有方法进行代理。

    public interface MethodInterceptor

    extends Callback

    {

        /**

         * 拦截方法逻辑

         *

         * @param o           被增强的对象

         * @param method      被增强的方法

         * @param args        方法的参数

         * @param methodProxy 方法的代理对象

         * @return 方法返回值

         */

        public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,

                                   MethodProxy proxy) throws Throwable;

    }

    Enhancer.create(object.getClass(), methodInterceptor)

    Spring AOP 创建代理过程

    下面介绍了Spring Aop支持AspectJ注解的代理创建过程, 其他注解的AOP类似,只是通过不同的扩展点来创建代理对象,如ProxyFactoryBean或BeanPostProcessor。

    @EnableAspectJAutoProxy

    项目为启用AspectJ的Spring-AOP,通常会再配置文件中加上@EnableAspectJAutoProxy

    @Target(ElementType.TYPE)

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    @Import(AspectJAutoProxyRegistrar.class)

    public @interface EnableAspectJAutoProxy {

             boolean proxyTargetClass() default false;

             boolean exposeProxy() default false;

    }

    @Import(AspectJAutoProxyRegistrar.class)

    @Import 注解包含一个实现了ImportBeanDefinitionRegistrar的类, 注册重要的Bean用于后续Bean初始化。AspectJAutoProxyRegistrar

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

                              }

                      }

             }

    AnnotationAwareAspectJAutoProxyCreator

    AnnotationAwareAspectJAutoProxyCreator负责创建AOP代理,实现了SmartInstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor) 接口,核心创建逻辑在postProcessBeforeInstantiation实现中。

    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {

             //缓存Bean类和名称,避免重复处理

             Object cacheKey = getCacheKey(beanClass, beanName);

             if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {

                      if (this.advisedBeans.containsKey(cacheKey)) {

                              return null;

                      }

                      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {

                              this.advisedBeans.put(cacheKey, Boolean.FALSE);

                              return null;

                      }

             }

             // Create proxy here if we have a custom TargetSource.

             // Suppresses unnecessary default instantiation of the target bean:

             // The TargetSource will handle target instances in a custom fashion.

             TargetSource targetSource = getCustomTargetSource(beanClass, beanName);

             if (targetSource != null) {

                      if (StringUtils.hasLength(beanName)) {

                              this.targetSourcedBeans.add(beanName);

                      }

                      //检查AOP相关配置是否作用在Bean上,如果不匹配这里返回空, 再下一步创建proxy将返回空

                      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);

                      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);

                      this.proxyTypes.put(cacheKey, proxy.getClass());

                      return proxy;

             }

             return null;

    }

    检查是否该创建Bean对象的逻辑在AopUtils.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 {

                      // It doesn't have a pointcut so we assume it applies.

                      return true;

             }

    }

    AopProxyFactory

    继续跟进代码 最终由AopProxyFactory来创建。 AopProxyFactory 调用AopProxy接口的getProxy方法创建代理对象。 AopProxy有两个实现:JdkDynamicAopProxy和ObjenesisCglibAopProxy对应于JDK动态代理和Cglib代理实现。

    选择AopProxy的代码如下:

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

                      if (!NativeDetector.inNativeImage() &&

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

                              }

                              if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {

                                       return new JdkDynamicAopProxy(config);

                              }

                              return new ObjenesisCglibAopProxy(config);

                      }

                      else {

                              return new JdkDynamicAopProxy(config);

                      }

             }

    具体创建代理的代码为Cglib和JDK代理的使用方法。如JdkDynamicAopProxy的getProxy()代码如下:

    public Object getProxy(@Nullable ClassLoader classLoader) {

                      if (logger.isTraceEnabled()) {

                              logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());

                      }

                      return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);

             }

    Spring AOP切面相关抽象及解析过程

    主要抽象
    Advice

    Org.aopalliance.aop.Advice: AOP联盟的Advice接口,代表增强入口,其实现包括Interceptors或其他任何类型的Advice。

    Org.aopalliance.intercept.interceptor: : 指可以针对Joint事件进行拦截的拦截器。

    MethodInterceptor:对接口调用的拦截

    public interface MethodInterceptor extends Interceptor {

      @Nullable

      Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;

    }

    ConstructorInterceptor: 对对象构造的拦截

    DynamicIntroductionAdvice:支持在Advice上实现附加接口。

    public interface DynamicIntroductionAdvice extends Advice {

      boolean implementsInterface(Class intf);

    }

    IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice : 通过Interceptor实现DynamicIntroductionAdvice。

           IntroductionInfo: 描述引入接口的信息

    MethodBeforeAdvice: 在方法调用之前执行的Advice

    AfterReturningAdvice: 在方法返回之后执行的Advice

    ThrowsAdvice: 异常抛出后执行的Advice

           public void afterThrowing(Exception ex)

           public void afterThrowing(RemoteException)

           public void afterThrowing(Method method, Object[] args, Object target, Exception ex)

           public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

    ClassFilter

    ClassFilter: 负责检查一个pointcut 或则 introduction时候和目标类匹配

    public interface ClassFilter {

      boolean matches(Class clazz);

    }

    MethodMatcher

    MethodMatcher:负责检查方法是否匹配Advice

    public interface MethodMatcher {

             boolean matches(Method method, Class targetClass);

             boolean isRuntime();

             boolean matches(Method method, Class targetClass, Object... args);

    }

    Advisor

    Advisor: 持有AOP Advice信息的接口,

    public interface Advisor {

      //返回切面的Advice信息, Advice指interceptor、before advice 、throw advice等

      Advice getAdvice();

      //Advisor是否共享

      boolean isPerInstance();

    }

    AdvisorChainFactory

    实现类DefaultAdvisorChainFactory,接口方法getInterceptorsAndDynamicInterceptionAdvice返回指定方法的Advice链(增强链),当执行代理对象时根据这里放回的Advice链进行增强。

    for (Advisor advisor : advisors) {

             if (advisor instanceof PointcutAdvisor) {

                      // Add it conditionally.

                      PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

                      if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

                              MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();

                              boolean match;

                              if (mm instanceof IntroductionAwareMethodMatcher) {

                                       if (hasIntroductions == null) {

                                                hasIntroductions = hasMatchingIntroductions(advisors, actualClass);

                                       }

                                       match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);

                              }

                              else {

                                       match = mm.matches(method, actualClass);

                              }

                              if (match) {

                                       MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

                                       if (mm.isRuntime()) {

                                                // Creating a new object instance in the getInterceptors() method

                                                // isn't a problem as we normally cache created chains.

                                                for (MethodInterceptor interceptor : interceptors) {

                                                         interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));

                                                }

                                       }

                                       else {

                                                interceptorList.addAll(Arrays.asList(interceptors));

                                       }

                              }

                      }

             }

             else if (advisor instanceof IntroductionAdvisor) {

                      IntroductionAdvisor ia = (IntroductionAdvisor) advisor;

                      if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {

                              Interceptor[] interceptors = registry.getInterceptors(advisor);

                              interceptorList.addAll(Arrays.asList(interceptors));

                      }

             }

             else {

                      Interceptor[] interceptors = registry.getInterceptors(advisor);

                      interceptorList.addAll(Arrays.asList(interceptors));

             }

    }

    Advised

    Advised是AOP的配置信息, AOP代理的创建时基于Advised提供的Advise及Advisor信息创建。

    如:Advised接口提供了Advisor的管理方法(get/addAdvisors)。

    AopContext

    AopContext 提供AOP线程上线文的。

    ThreadLocal currentProxy = new NamedThreadLocal<>("Current AOP proxy");

    ProxyConfig

    AOP 代理创建的配置类, 提取公共父类保证代理的一致性。

    ProxyConfig作为AOP代理创建代理对象的一个基础类,其实现展示了几种代理的实现机制。

    BeanFactoryAware+BeanPostProcessor方式

    AbstractAdvisingBeanPostProcessor及其子类使用该模式进行框架初始化, 该模式针对特定切面,如Async。通过setBeanFactory方法初始Advisor信息, 并在postProcessAfterInitialization方法中创建代理对象。

    AsyncAnnotationBeanPostProcessor

    @Override

    public void setBeanFactory(BeanFactory beanFactory) {

             super.setBeanFactory(beanFactory);

             AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);

             if (this.asyncAnnotationType != null) {

                      advisor.setAsyncAnnotationType(this.asyncAnnotationType);

             }

             advisor.setBeanFactory(beanFactory);

             this.advisor = advisor;

    }

    @Override

    public Object postProcessAfterInitialization(Object bean, String beanName) {

             ......

             if (isEligible(bean, beanName)) {

                      ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);

                      if (!proxyFactory.isProxyTargetClass()) {

                              evaluateProxyInterfaces(bean.getClass(), proxyFactory);

                      }

                      proxyFactory.addAdvisor(this.advisor);

                      customizeProxyFactory(proxyFactory);

                      // Use original ClassLoader if bean class not locally loaded in overriding class loader

                      ClassLoader classLoader = getProxyClassLoader();

                      if (classLoader instanceof SmartClassLoader && classLoader != bean.getClass().getClassLoader()) {

                              classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();

                      }

                      return proxyFactory.getProxy(classLoader);

             }

             // No proxy needed.

             return bean;

    }

    protected boolean isEligible(Class targetClass) {

             Boolean eligible = this.eligibleBeans.get(targetClass);

             if (eligible != null) {

                      return eligible;

             }

             if (this.advisor == null) {

                      return false;

             }

             eligible = AopUtils.canApply(this.advisor, targetClass);

             this.eligibleBeans.put(targetClass, eligible);

             return eligible;

    }

    基于SmartInstantiationAwareBeanPostProcessor的AutoProxyCreator

    AOP关于AspectJ注解的支持是基于该模式创建, 该模式的特点是: 1. 支持各种不同功能的切面增强。 2. 代理对象负责创建目标对象,支持目标对象的延迟创建。

    基于postProcessBeforeInstantiation接口创建。

    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {

             Object cacheKey = getCacheKey(beanClass, beanName);

             // Create proxy here if we have a custom TargetSource.

             // Suppresses unnecessary default instantiation of the target bean:

             // The TargetSource will handle target instances in a custom fashion.

             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;

    }

    相关代码见AbstractAutoProxyCreator及其子类, 在Spring AOP创建章节中详细介绍。

    初始化核心调用栈示例:

    getTransactionAttribute:93, AbstractFallbackTransactionAttributeSource (org.springframework.transaction.interceptor)

    matches:42, TransactionAttributeSourcePointcut (org.springframework.transaction.interceptor)

    canApply:251, AopUtils (org.springframework.aop.support)

    canApply:288, AopUtils (org.springframework.aop.support)

    findAdvisorsThatCanApply:320, AopUtils (org.springframework.aop.support)

    findAdvisorsThatCanApply:126, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)

    findEligibleAdvisors:95, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)

    getAdvicesAndAdvisorsForBean:76, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)

    wrapIfNecessary:352, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)

    postProcessAfterInitialization:304, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)

    基于FactoryBean模式创建代理

    @Transaction及@Cache注解的创建模式

    AbstractSingletonProxyFactoryBean

    public void afterPropertiesSet() {

             ProxyFactory proxyFactory = new ProxyFactory();

             if (this.preInterceptors != null) {

                      for (Object interceptor : this.preInterceptors) {

                              proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));

                      }

             }

             // Add the main interceptor (typically an Advisor).

             proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

             if (this.postInterceptors != null) {

                      for (Object interceptor : this.postInterceptors) {

                              proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));

                      }

             }

             proxyFactory.copyFrom(this);

             TargetSource targetSource = createTargetSource(this.target);

             proxyFactory.setTargetSource(targetSource);

             if (this.proxyInterfaces != null) {

                      proxyFactory.setInterfaces(this.proxyInterfaces);

             }

             else if (!isProxyTargetClass()) {

                      // Rely on AOP infrastructure to tell us what interfaces to proxy.

                      Class targetClass = targetSource.getTargetClass();

                      if (targetClass != null) {

                              proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));

                      }

             }

             postProcessProxyFactory(proxyFactory);

             this.proxy = proxyFactory.getProxy(this.proxyClassLoader);

    }

    protected Object createMainInterceptor() {

             this.transactionInterceptor.afterPropertiesSet();

             if (this.pointcut != null) {

                      return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);

             }

             else {

                      // Rely on default pointcut.

                      return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);

             }

    }

    //TransactionProxyFactoryBean

    AopProxy

    AOP 代理接口实现类包括Cglib和Jdk动态代理

          

    AopProxyFactory

    AopProxy工厂接口,负责创建AopProxy对象。实现类是DefaultAopProxyFactory

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

                      }

                      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {

                              return new JdkDynamicAopProxy(config);

                      }

                      return new ObjenesisCglibAopProxy(config);

    注解信息的解析(Advised对象的创建)

    Advised对象的解析过程同ProxyConfig章节介绍的代理对象过程类似,同样是三种模式的解析过程。

    AbstractAdvisingBeanPostProcessor

    AbstractAdvisingBeanPostProcessor 针对特定注解创建代理对象模式。扩展点BeanPostProcessor 的postProcessAfterInitialization方法中检查注解是否作用在Bean上,如是则创建代理。

    if (isEligible(bean, beanName)) {

             ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);

             if (!proxyFactory.isProxyTargetClass()) {

                      evaluateProxyInterfaces(bean.getClass(), proxyFactory);

             }

             proxyFactory.addAdvisor(this.advisor);

             customizeProxyFactory(proxyFactory);

             // Use original ClassLoader if bean class not locally loaded in overriding class loader

             ClassLoader classLoader = getProxyClassLoader();

             if (classLoader instanceof SmartClassLoader && classLoader != bean.getClass().getClassLoader()) {

                      classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();

             }

             return proxyFactory.getProxy(classLoader);

    }

    AbstractSingletonProxyFactoryBean

    基于FactoryBean机制,对通过XML配置的FactoryBean,针对目标Bean解析所得Advicsed对象。

             custom

             666

            

               abstract="true">

            

            

                     

                              PROPAGATION_MANDATORY

                                PROPAGATION_REQUIRED  ,  readOnly 

                              PROPAGATION_SUPPORTS

                     

            

             true

            

    public void afterPropertiesSet() {

             ProxyFactory proxyFactory = new ProxyFactory();

             if (this.preInterceptors != null) {

                      for (Object interceptor : this.preInterceptors) {

                              proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));

                      }

             }

             // Add the main interceptor (typically an Advisor).

             proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

             if (this.postInterceptors != null) {

                      for (Object interceptor : this.postInterceptors) {

                              proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));

                      }

             }

             proxyFactory.copyFrom(this);

             TargetSource targetSource = createTargetSource(this.target);

             proxyFactory.setTargetSource(targetSource);

             if (this.proxyInterfaces != null) {

                      proxyFactory.setInterfaces(this.proxyInterfaces);

             }

             else if (!isProxyTargetClass()) {

                      // Rely on AOP infrastructure to tell us what interfaces to proxy.

                      Class targetClass = targetSource.getTargetClass();

                      if (targetClass != null) {

                              proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));

                      }

             }

             postProcessProxyFactory(proxyFactory);

             this.proxy = proxyFactory.getProxy(this.proxyClassLoader);

    }

    ProxyFactoryBean

    基于ProxyFactoryBean创建的代理的对象,在获取对象时会检查是否需要解析和创建AOP 的代理。

    public Object getObject() throws BeansException {

             initializeAdvisorChain();

             if (isSingleton()) {

                      return getSingletonInstance();

             }

             else {

                      if (this.targetName == null) {

                              logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +

                                                "Enable prototype proxies by setting the 'targetName' property.");

                      }

                      return newPrototypeInstance();

             }

    }

    Spring AOP的执行

    JDK代理执行代码

    JdkDynamicAopProxy 执行了JDK动态代理的InvocationHandler接口, 执行入口就是JdkDynamicAopProxy的invoke方法。

    流程:

    1. 获取该方法匹配的Advice

    // Get the interception chain for this method.

    List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    查找匹配实现为接口AdvisorChainFactory接口的实现类:DefaultAdvisorChainFactory。

    public interface AdvisorChainFactory {

             /**

              * Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects

              * for the given advisor chain configuration.

              * @param config the AOP configuration in the form of an Advised object

              * @param method the proxied method

              * @param targetClass the target class (may be {@code null} to indicate a proxy without

              * target object, in which case the method's declaring class is the next best option)

              * @return a List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)

              */

             List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class targetClass);

    }

    解析相应的MethodInterceptor接口实现或适配AOP 联盟的语言成为MethodInterceptor接口。

    如:MethodBeforeAdviceInterceptor代码如下:

    public Object invoke(MethodInvocation mi) throws Throwable {

             this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());

             return mi.proceed();

    }

    1. 执行

    // We need to create a method invocation...

    MethodInvocation invocation =  new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

    // Proceed to the joinpoint through the interceptor chain.

    retVal = invocation.proceed();

    1. ReflectiveMethodInvocation 处理方法

    public Object proceed() throws Throwable {

                      // We start with an index of -1 and increment early.

                      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;

                              Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());

                              if (dm.methodMatcher.matches(this.method, 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 {

                              // It's an interceptor, so we just invoke it: The pointcut will have

                              // been evaluated statically before this object was constructed.

                              return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

                      }

             }

    AopContext

    AopContext类可以再代理类执行过程中获取到代理对象, 通过代理对象可以保证基于AOP增强的特性得到执行,从而解决直接this.xxx调用直接执行被代理对象的方法,造成增强实效。

    Spring Aop 应用-@Transactional

           Spring Transaction就是基于Spring AOP机制实现的事务。

    解析@Transactionnal

           事务的拦截逻辑实现主要在TransactionInterceptor类中, 如果通过XML文件配置的TransactionProxyFactoryBean创建代理对象,则在FactoryBean的afterProperties方法中创建Advisor生成proxyFactory对象(见上面章节)。

    对于基于注解的Transaction注解解析在于TransactionAttributeSourcePointcut由AOP框架触发解析判断某个方法是否满足Transactional注解。

    解析逻辑代码如下:

    @Nullable

    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) {

             // Don't allow non-public methods, as configured.

             if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {

                      return null;

             }

             // The method may be on an interface, but we need attributes from the target class.

             // If the target class is null, the method will be unchanged.

             Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

             // First try is the method in the target class.

             TransactionAttribute txAttr = findTransactionAttribute(specificMethod);

             if (txAttr != null) {

                      return txAttr;

             }

             // Second try is the transaction attribute on the target class.

             txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());

             if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {

                      return txAttr;

             }

             if (specificMethod != method) {

                      // Fallback is to look at the original method.

                      txAttr = findTransactionAttribute(method);

                      if (txAttr != null) {

                              return txAttr;

                      }

                      // Last fallback is the class of the original method.

                      txAttr = findTransactionAttribute(method.getDeclaringClass());

                      if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {

                              return txAttr;

                      }

             }

             return null;

    }

    TransactionInterceptor

    事务执行逻辑实现与TransactionInterceptor

    public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

    // Standard transaction demarcation with getTransaction and commit/rollback calls.

    TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

    Object retVal;

    try {

             // This is an around advice: Invoke the next interceptor in the chain.

             // This will normally result in a target object being invoked.

             retVal = invocation.proceedWithInvocation();

    }

    catch (Throwable ex) {

             // target invocation exception

             completeTransactionAfterThrowing(txInfo, ex);

             throw ex;

    }

    finally {

             cleanupTransactionInfo(txInfo);

    }

    if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {

             // Set rollback-only in case of Vavr failure matching our rollback rules...

             TransactionStatus status = txInfo.getTransactionStatus();

             if (status != null && txAttr != null) {

                      retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);

             }

    }

    commitTransactionAfterReturning(txInfo);

    return retVal;

  • 相关阅读:
    Spring-Cloud如何异步跨线程查询链路日志(附实例)
    机器学习笔记之马尔可夫链蒙特卡洛方法(四)吉布斯采样
    【自学开发之旅】Flask-会话保持-API授权-注册登录
    【DLY-310端子排型电流继电器】
    煤矿皮带撕裂检测系统
    树莓派4b配置通过smbus2使用LCD灯
    【二十】【QT开发应用】listwidget右键菜单和删除item
    云服务器ip使用细节(公网、私有)
    ABP应用开发(Step by Step)-下篇
    Lambert (兰伯特)光照模型
  • 原文地址:https://blog.csdn.net/dreamsofa/article/details/133688130