spring源码分析——注解

本文介绍了一个自定义注解的实现方法,并通过Spring AOP实现了对带有该注解的方法进行环绕通知,同时展示了如何使用@Transactional注解来管理事务。

代码:https://github.com/shangjianan2/NormalTechnology.git

自定义注解

定义注解

package com.ework.upms.server.annotation;

import java.lang.annotation.*;

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

定义切面

package com.ework.upms.server.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAspect {

    @Around("@annotation(com.ework.upms.server.annotation.MyAnnotation)")
    public Object testAround(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("aspect pre");
        Object o = jp.proceed();
        System.out.println("aspect post");
        return o;
    }
}

使用

Service

package com.ework.upms.server.service;

import com.ework.upms.server.annotation.MyAnnotation;
import org.springframework.stereotype.Service;

@Service
public class TestAspect {
    @MyAnnotation
    public String helloWorld() {
        return "adsf";
    }

}

Test

package com.ework.upms.server.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

@ContextConfiguration(locations = {"classpath:spring-servlet.xml"})
public class testAspectTest extends AbstractTestNGSpringContextTests {
    @Autowired
    private TestAspect testAspect;
    @Autowired
    private TestTransaction testTransaction;

    @Test
    public void test() {
        testAspect.helloWorld();
        testTransaction.helloWorld();
    }
}


断点调试

调用堆栈

helloWorld:10, TestAspect (com.ework.upms.server.service)//原方法
invoke:-1, TestAspect$$FastClassBySpringCGLIB$$9c26b26 (com.ework.upms.server.service)
invoke:204, MethodProxy (org.springframework.cglib.proxy)//从这里开始调用原方法
invokeJoinpoint:738, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:157, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:85, MethodInvocationProceedingJoinPoint (org.springframework.aop.aspectj)
testAround:15, MyAspect (com.ework.upms.server.aspect)//处理注解所用的切面
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)//调用切面的前一刻
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeAdviceMethodWithGivenArgs:629, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invokeAdviceMethod:618, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invoke:70, AspectJAroundAdvice (org.springframework.aop.aspectj)
proceed:168, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:92, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:179, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:673, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)//在这里可以看到切面所构成的list,chain
helloWorld:-1, TestAspect$$EnhancerBySpringCGLIB$$a0acf715 (com.ework.upms.server.service)
test:17, testAspectTest (com.ework.upms.server.service)
//下面还有一些关于单元测试的调用,在此省略

查看intercept:673, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)中可以看到下面的chain
在这里插入图片描述
稍微展开一下
在这里插入图片描述
在调用调用自定义切面代码的前一刻invoke:62, NativeMethodAccessorImpl (sun.reflect)
在这里插入图片描述
上图中的this.method.clazz与之前的chain[1].interceptor.declaringClass使用的是同一个对象

Transactional

貌似应用上下文中需要有事务管理器才能触发Transactional的增强效果,如果没有事务管理器则不会用动态代理对代码进行增强

使用

Service

package com.ework.upms.server.service;

import com.ework.upms.server.annotation.MyAnnotation;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TestTransaction {

    @Transactional(transactionManager = "adsTm")
    public String helloWorld() {
        return "adsf";
    }

}

Test

package com.ework.upms.server.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

@ContextConfiguration(locations = {"classpath:spring-servlet.xml"})
public class testAspectTest extends AbstractTestNGSpringContextTests {
    @Autowired
    private TestAspect testAspect;
    @Autowired
    private TestTransaction testTransaction;

    @Test
    public void test() {
        testAspect.helloWorld();
        testTransaction.helloWorld();
    }
}

断点调试

调用堆栈

helloWorld:13, TestTransaction (com.ework.upms.server.service)
invoke:-1, TestTransaction$$FastClassBySpringCGLIB$$da198cd0 (com.ework.upms.server.service)
invoke:204, MethodProxy (org.springframework.cglib.proxy)//从这里开始调用原方法,与上文相同
invokeJoinpoint:738, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:157, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceedWithInvocation:99, TransactionInterceptor$1 (org.springframework.transaction.interceptor)
invokeWithinTransaction:282, TransactionAspectSupport (org.springframework.transaction.interceptor)//这里可以看到事务创建消除过程
invoke:96, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:179, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:673, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
helloWorld:-1, TestTransaction$$EnhancerBySpringCGLIB$$c05525c8 (com.ework.upms.server.service)
test:18, testAspectTest (com.ework.upms.server.service)

invokeWithinTransaction:282, TransactionAspectSupport (org.springframework.transaction.interceptor)中可以看到如下代码

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			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();//这个方法是从入参InvocationCallback中传递过来的
			}
			catch (Throwable ex) {
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值