spring aop介绍
spring提供了五种通知类型
- Interception Around
JointPoint前后调用,实现此类需要实现接口MethodInterceptor。
- Before通知
需要实现接口MethodBeforeAdvice。
- After Returning 通知
需要实现接口AfterReturningAdvice。
- Throw通知
需要实现接口ThrowsAdvice
- Introduction通知
需要实现接口IntroductionAdvisor和IntroductionInterceptor。
怎样实现自己的事务管理器
package com.july.testspring.transaction;
public interface StudentService {
public boolean insert(StudentDemo demo);
public boolean insert2(StudentDemo studentDemo);
}
package com.july.testspring.transaction;
import java.io.Serializable;
public class StudentDemo implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "StudentDemo [id=" + id + ", name=" + name + "]";
}
}
package com.july.testspring.transaction;
public class StudentServiceImpl implements StudentService {
@Override
public boolean insert(StudentDemo demo) {
System.out.println("insert success!");
return true;
}
@Override
public boolean insert2(StudentDemo studentDemo) {
System.out.println(1/0);
return false;
}
}
package com.july.testspring.transaction;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.StringUtils;
public class MyTransactionInterceptor implements MethodInterceptor {
final ThreadLocal<TransactionInfo> transactionThread = new ThreadLocal<TransactionInfo>();
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Class targetClass = (methodInvocation.getThis() != null) ? methodInvocation.getThis().getClass() : null;
//
if(methodInvocation.getMethod().getName().equals("toString")) {
return "";
}
//begin Transaction
TransactionInfo txInfo = createTransactionIfNecessary(methodInvocation.getMethod(), methodInvocation);
Object retVal = null;
try {
retVal = methodInvocation.proceed();
}catch (Throwable e) {
//回滚相关事务 父类或子类实现
doCloseTransactionAfterThrowing(geTransactionInfo(), e);
throw e;
} finally {
//设置transaction 状态
TransactionInfo info = geTransactionInfo();
info.setSuccessStatus(StatusType.SUCCESS);
doFinally(info);
}
//commit
doCommitTransactionAfterReturning(geTransactionInfo());
return retVal;
}
private void doFinally(TransactionInfo transactionInfo) {
setTransactionInfo(transactionInfo);
}
private void doCommitTransactionAfterReturning(com.july.testspring.transaction.TransactionInfo geTransactionInfo) {
System.out.println("docommit");
}
private void doCloseTransactionAfterThrowing(com.july.testspring.transaction.TransactionInfo geTransactionInfo,
Throwable e) {
System.out.println("rollback transaction");
}
private com.july.testspring.transaction.TransactionInfo createTransactionIfNecessary(Method method,
MethodInvocation methodInvocation) {
System.out.println("begin transation");
TransactionInfo transactionInfo = new TransactionInfo();
setTransactionInfo(transactionInfo);
return transactionInfo;
}
public TransactionInfo geTransactionInfo() {
return transactionThread.get();
}
public void setTransactionInfo(TransactionInfo transactionInfo) {
transactionThread.set(transactionInfo);
}
}
- JDK动态代理InvocationHandler,实现InvocationHandler接口。
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.Advised;
public class ProxyFactory implements InvocationHandler {
public Object target;
Advice advisor = (Advice) new MyTransactionInterceptor();
public ProxyFactory(Object target) {
this.target = target;
}
/*private static class ProxyFactoryClient {
private static final ProxyFactory PROXY_FACTORY = new ProxyFactory();
}*/
/**
* 创建代理
*
* @param classzz
* @return
*/
public <T> T createProxy(Class<?> target) {
return (T) Proxy.newProxyInstance(getClassLoader(),getMethodInterceptor(target), this);
}
private Class[] getMethodInterceptor(Class<?> target) {
return target.getInterfaces();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation methodInvocation = new TransactionMethodInvocation(args, target, method, this.advisor);
return methodInvocation.proceed();
}
private ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
}
- 实现MethodInvocation接口 TransactionMethodInvocation
package com.july.testspring.transaction;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
public class TransactionMethodInvocation implements MethodInvocation{
protected Object[] arguments;
protected final Object target;
protected final Method method;
Advice interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
public TransactionMethodInvocation(Object[] arguments,Object target,Method method,Advice interceptorsAndDynamicMethodMatchers) {
this.arguments = arguments;
this.target = target;
this.method = method;
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
@Override
public Object[] getArguments() {
return this.arguments;
}
@Override
public AccessibleObject getStaticPart() {
return this.method;
}
@Override
public Object getThis() {
return this.target;
}
@Override
public Object proceed() throws Throwable {
if(++currentInterceptorIndex == 1) {
return this.method.invoke(this.target, this.arguments);
}
return ((MethodInterceptor) interceptorsAndDynamicMethodMatchers).invoke(this);
}
@Override
public Method getMethod() {
return this.method;
}
}
import java.util.concurrent.atomic.AtomicLong;
public class TransactionInfo {
//1 成功 0 失败
private volatile int status = 0;
private final AtomicLong atomicLong = new AtomicLong();
public void setSuccessStatus(StatusType type) {
if(type.getCode() != status) {
atomicLong.compareAndSet(0, type.getCode());
}
}
public void setFailStatus(StatusType type) {
if(type.getCode() != status) {
atomicLong.compareAndSet(1, type.getCode());
}
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.july.testspring.service.UserService;
import com.july.testspring.service.impl.UserServiceImpl;
public class Test {
public static void main(String[] args) {
StudentService userService2 = new ProxyFactory(new StudentServiceImpl()).createProxy(StudentServiceImpl.class);
System.out.println("开始执行insert方法");
System.out.println("方法返回值 : " + userService2.insert(new StudentDemo()));
System.out.println("====================================");
System.out.println("开始执行insert2方法");
System.out.println(userService2.insert2(new StudentDemo()));
}
}
begin transation
insert success!
docommit
方法返回值 : true
====================================
开始执行insert2方法
begin transation
rollback transaction
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy0.insert2(Unknown Source)
at com.july.testspring.transaction.Test.main(Test.java:26)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.july.testspring.transaction.TransactionMethodInvocation.proceed(TransactionMethodInvocation.java:49)
at com.july.testspring.transaction.MyTransactionInterceptor.invoke(MyTransactionInterceptor.java:26)
at com.july.testspring.transaction.TransactionMethodInvocation.proceed(TransactionMethodInvocation.java:51)
at com.july.testspring.transaction.ProxyFactory.invoke(ProxyFactory.java:51)
... 2 more
Caused by: java.lang.ArithmeticException: / by zero
at com.july.testspring.transaction.StudentServiceImpl.insert2(StudentServiceImpl.java:13)
... 10 more