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> 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<Object> 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对象。

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <bean id="target" class="org.springframework.beans.testfixture.beans.DerivedTestBean" lazy-init="true"> <property name="name"><value>custom</value></property> <property name="age"><value>666</value></property> <property name="spouse"><ref bean="targetDependency"/></property> </bean> <bean id="baseProxyFactory" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager"><ref bean="mockMan"/></property> <property name="transactionAttributes"> <props> <prop key="s*">PROPAGATION_MANDATORY</prop> <prop key="setAg*"> PROPAGATION_REQUIRED , readOnly </prop> <prop key="set*">PROPAGATION_SUPPORTS</prop> </props> </property> </bean> <bean id="proxyFactory2Cglib" parent="baseProxyFactory"> <property name="proxyTargetClass"><value>true</value></property> <property name="target"><ref bean="target"/></property> </bean> |
| 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<Object> 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<Object> 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; |

相关推荐
IT学长编程7 分钟前
计算机毕业设计 Java酷听音乐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·音乐系统·计算机毕业设计选题
IT学长编程24 分钟前
计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·毕业论文·协同过滤算法·计算机毕业设计选题·个性化音乐推荐系统
小小娥子29 分钟前
Redis的基础认识与在ubuntu上的安装教程
java·数据库·redis·缓存
几何心凉37 分钟前
已解决:org.springframework.web.HttpMediaTypeNotAcceptableException
java
华农第一蒟蒻39 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
两点王爷41 分钟前
使用WebClient 快速发起请求(不使用WebClientUtils工具类)
java·网络
计算机学姐1 小时前
基于SpringBoot+Vue的高校运动会管理系统
java·vue.js·spring boot·后端·mysql·intellij-idea·mybatis
平凡的小码农1 小时前
JAVA实现大写金额转小写金额
java·开发语言
一直在进步的派大星1 小时前
Docker 从安装到实战
java·运维·docker·微服务·容器
老华带你飞1 小时前
公寓管理系统|SprinBoot+vue夕阳红公寓管理系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·spring boot·课程设计