代码: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;
}

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

被折叠的 条评论
为什么被折叠?



