SpringAop源碼解讀

一、實例:

切點類:

package com.hxm.aop;

public class MathCalculator {
    public int div(int i, int j){
        System.out.println("執行除法");
        return i/j;
    }
}

切面類:

@Aspect
public class LogAspects {

    //公共切點表達式
    @Pointcut("execution(public int com.hxm.aop.MathCalculator.*(..))")
    public void pointCut(){

    }

    //1、可以直接寫切點表達式
    @Before("execution(public int com.hxm.aop.MathCalculator.*(..))")
    public void logStart(){
        System.out.println("除法運行,參數列表是:{}");
    }

    //2、也可以寫公共的切點函數,在本類中直接寫方法名
    @After(value = "pointCut()")
    public void logEnd(){
        System.out.println("除法結束");
    }

    //3、外部類寫公共切點函數的全類名
    @AfterReturning(value = "com.hxm.aop.LogAspects.pointCut()",returning = "result")
    public void logReturn(Object result){
        System.out.println("除法正常返回,運行結果:{"+result+"}");
    }

    @AfterThrowing(value = "pointCut()",throwing = "exception")
    public void logException(Exception exception){
        System.out.println("除法異常,異常信息:{}");
    }
}

將切點類與切面類註冊到容器中:

@EnableAspectJAutoProxy
@Configuration
public class AopConfig {

    @Bean
    public MathCalculator calculator(){
        return new MathCalculator();
    }

    @Bean
    public LogAspects logAspects(){
        return new LogAspects();
    }
}

二、源碼:

2.1 AOP功能的注入

起點:@EnableAspectJAutoProxy註解

@EnableAspectJAutoProxy
@Configuration
public class AopConfig {}

點進@EnableAspectJAutoProxy

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {}

發現用@Import導入了一個AspectJAutoProxyRegistrar。進入AspectJAutoProxyRegistrar,一路跟進下去,發現向容器中註冊了一個AnnotationAwareAspectJAutoProxyCreator,並命名爲internalAutoProxyCreator:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      	//註冊
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    // 注意在這個方法中已經把AnnotationAwareAspectJAutoProxyCreator的字節碼傳入方法了
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
        "org.springframework.aop.config.internalAutoProxyCreator";

private static BeanDefinition registerOrEscalateApcAsRequired(
        Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  	//註冊
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

AnnotationAwareAspectJAutoProxyCreator的繼承關係:

2.2 AnnotationAwareAspectJAutoProxyCreator後置處理功能

2.3 jdk & Cglib執行調用鏈

三、註解事務:

3.1 註解事務的注入

@EnableTransactionManagement
@Configuration
public class AopConfig {}

點進 @EnableTransactionManagement:

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
	boolean proxyTargetClass() default false;

	AdviceMode mode() default AdviceMode.PROXY;

	int order() default Ordered.LOWEST_PRECEDENCE;
}

點進 @TransactionManagementConfigurationSelector,發現他繼承 ImportSelector,即通過組件的全限定類名向IOC容器註冊bean:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
            //默認是這種方式
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}
}

向容器中組冊了AutoProxyRegistrarProxyTransactionManagementConfiguration.

3.1.1 AutoProxyRegistrar

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
		for (String annType : annTypes) {
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
			if (candidate == null) {
				continue;
			}
			Object mode = candidate.get("mode");
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				if (mode == AdviceMode.PROXY) {
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
	}
}

實現了ImportBeanDefinitionRegistrar,即通過registry.registerBeanDefinition向容器中註冊組件。registerAutoProxyCreatorIfNecessary:

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
        @Nullable Object source) {
    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
        @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

發現向容器中註冊了InfrastructureAdvisorAutoProxyCreator,他的繼承關係:

發現InfrastructureAdvisorAutoProxyCreator和之前的AnnotationAwareAspectJAutoProxyCreator異曲同工。

3.1.2 ProxyTransactionManagementConfiguration

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		advisor.setAdvice(transactionInterceptor());
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor() {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}
}

發現向容器中註冊了3個bean:

1. BeanFactoryTransactionAttributeSourceAdvisor:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};

	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionAttributeSource = transactionAttributeSource;
	}

	public void setClassFilter(ClassFilter classFilter) {
		this.pointcut.setClassFilter(classFilter);
	}

	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}
}

Advisor是增強器,通過pointcut(切入點)來增強方法,而pointcut又依賴TransactionAttributeSource。

2. TransactionAttributeSource:讀取/解析@Transactional註解

3. TransactionInterceptor:

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable

可以看出他是一個MethodInterceptor,即事務的功能主要是由它控制的。

3.2 註解事務的工作流程

首先創建一個事務demo:

@Service
public class DemoService {
    
    @Transactional(rollbackFor = Exception.class)
    public void test1() {
        System.out.println("test1 run...");
        int i = 1 / 1;
        System.out.println("test1 finish...");
    }
}

在調用方法時,由於不是接口,所以返回CglibAopProxy產生的代理類,並執行intercept方法:

class CglibAopProxy implements AopProxy, Serializable{
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        Object retVal;
        // ......
        retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
        // ......
    }
}

此時,chain中有TransactionInterceptor:

進而執行TransactionInterceptor的invoke:

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
    public Object invoke(MethodInvocation invocation) throws Throwable {
        
        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

        return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
    }
    
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
                                             final InvocationCallback invocation) throws Throwable {

        TransactionAttributeSource tas = getTransactionAttributeSource();
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        //獲取事務管理器
        final TransactionManager tm = determineTransactionManager(txAttr);

        if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
            // 創建事務
            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);
            }
            //提交事務
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }
}

四、事務傳播行爲的原理

4.1 事務的幾種傳播行爲

4.2 傳播行爲原理

五、自定義AOP增強器

4.1以註解事務爲例,首先要明確幾個概念:

1. Advisor:增強器,BeanFactoryTransactionAttributeSourceAdvisor,其繼承關係如下:

Advisor要依靠Pointcut來確定要增強的類和方法,以及依靠advice(即Interceptor,也叫攔截器)去執行真正的增強操作。

2. Pointcut:切點,TransactionAttributeSourcePointcut,其繼承關係如下:

通過matches方法來確定要增強的類和方法。

3. Invocation:執行器如CglibMethodInvocation,其繼承關係如下:

當代理對象的invoke被執行時,所有的增強方法advice鏈chain和真正的調用方法method會被包裝成一個Invocation,並調用Invocation.proceed()。proceed會執行一下兩種流程:當chain中還有advice時,調用advice的invoke執行增強方法,並把自己傳入;當chain中無還未執行過的advice時,則反射調用method執行真正的方法。

4. advice:增強方法,TransactionInterceptor,其繼承關係如下:

當advice的invoke被調用時,同時被傳入了Invocation,可以在調用Invocation.proceed進行後續攔截器鏈調用的前後以及拋出異常時,執行自己的增強方法。

4.2 實現自己的註解增強器

由此可見,要想實現一個自己的增強器,需要實現Advisor、Pointcut以及Interceptor。由於我們要實現一個自定義註解增強器,所以還需要實現一個註解解析器。

Advisor:

public class MyAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    @Autowired
    private MyPointCut pointCut;

    @Override
    public Pointcut getPointcut() {
        return pointCut;
    }
}

PointCut:

public class MyPointCut extends StaticMethodMatcherPointcut {

    /**
     * 註解解析器
     */
    @Autowired
    MyAttributeSource attributeSource;

    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        return attributeSource.getAttribute(method,targetClass);
    }
}

Interceptor:

public class MyInterceptor implements MethodInterceptor {
    
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("執行前");
        try {
            return invocation.proceed();
        } finally {
            System.out.println("執行後");
        }
    }
}

增強註解:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAop {
}

註解解析器:

public class MyAttributeSource {
    public boolean getAttribute(Method method, Class<?> targetClass){
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                specificMethod, MyAop.class, false, false);
        if(attributes!=null){
            return true;
        }
        return false;
    }
}

config配置類:

@ComponentScan("com.hxm")
@Configuration

public class AopConfig {
	/**
	 * 需要將攔截器注入
	 */
    @Bean
    public MyAdvisor myAdvisor(){
        MyAdvisor myAdvisor=new MyAdvisor();
        myAdvisor.setAdvice(myInterceptor());
        return myAdvisor;
    }

    @Bean
    public MyInterceptor myInterceptor(){
        return new MyInterceptor();
    }

    @Bean
    public MyAttributeSource myAttributeSource(){
        return new MyAttributeSource();
    }

    @Bean
    public MyPointCut myPointCut(){
        return new MyPointCut();
    }

}

測試類:

@Service
public class MyAopDemo {

    @MyAop
    public void test(){
        System.out.println("im aop demo");
    }
}

主類:

public class TxTest {
    public static void main(String[] args) {

        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(AopConfig.class);
        MyAopDemo demo=applicationContext.getBean(MyAopDemo.class);
        demo.test();
    }
}

結果:

執行前
im aop demo
執行後
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章