Dynamic Proxy 与Spring AOP
Spring中提供的内置AOP支持,是基于动态AOP机制实现。从技术角度来讲,所谓动
态AOP,即通过动态Proxy模式,在目标对象的方法调用前后插入相应的处理代码。
而Spring AOP中的动态Proxy模式,则是基于Java Dynamic Proxy(面向Interface)
和CGLib(面向Class)实现。
前面曾经提及,Spring Framework中的“事务管理”服务,实际上是借助AOP机制
完成。我们这里就以“事务管理”为例,对动态AOP的实现加以探讨,一方面对动态AOP
的实现原理加以探究,另一方面,也可以加深对Spring中事务管理机制的理解。
以下是Dynamic Proxy的例子:
AOPHandler.java
package aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AOPHandler implements InvocationHandler {
private static Log logger = LogFactory.getLog(AOPHandler.class);
private List interceptors = null;
private Object originalObject;
/**
* 返回动态代理实例
* @param obj
* @return
*/
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj
.getClass().getInterfaces(), this);
}
/**
* 在Invoke方法中,加载对应的Interceptor,并进行
* 预处理(before)、后处理(after)以及异常处理(exceptionThrow)过程
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Throwable ex = null;
InvocationInfo invInfo = new InvocationInfo(proxy, method, args,
result, ex);
logger.debug("Invoking Before Intercetpors!");
System.out.println("Invoking Before Intercetpors!");
invokeInterceptorsBefore(invInfo);
try {
logger.debug("Invoking Proxy Method!");
System.out.println("Invoking Proxy Method!");
result = method.invoke(originalObject, args);
invInfo.setResult(result);
logger.debug("Invoking After Method!");
System.out.println("Invoking After Method!");
invokeInterceptorsAfter(invInfo);
} catch (Throwable tr) {
invInfo.setException(tr);
logger.debug("Invoking exceptionThrow Method!");
System.out.println("Invoking exceptionThrow Method!");
invokeInterceptorsExceptionThrow(invInfo);
throw new AOPRuntimeException(tr);
}
return result;
}
/**
* 加载Interceptor
* @return
*/
private synchronized List getIntercetors() {
if (null == interceptors) {
interceptors = new ArrayList();
//Todo:读取配置,加载Interceptor实例
interceptors.add(new MyInterceptor());
}
return interceptors;
}
/**
* 执行预处理方法
* @param invInfo
*/
private void invokeInterceptorsBefore(InvocationInfo invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = 0; i < len; i++) {
((Interceptor) interceptors.get(i)).before(invInfo);
}
}
/**
* 执行后处理方法
* @param invInfo
*/
private void invokeInterceptorsAfter(InvocationInfo invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = len - 1; i >= 0; i--) {
((Interceptor) interceptors.get(i)).after(invInfo);
}
}
/**
* 执行异常处理方法
* @param invInfo
*/
private void invokeInterceptorsExceptionThrow(InvocationInfo
invInfo) {
List interceptors = getIntercetors();
int len = interceptors.size();
for (int i = len - 1; i >= 0; i--) {
((Interceptor)
interceptors.get(i)).exceptionThrow(invInfo);
}
}
}
AOPRuntimeException.java 异常处理
package aop;
public class AOPRuntimeException extends RuntimeException {
AOPRuntimeException(Throwable e)
{
}
}
Interceptor.java拦截器接口
package aop;
public interface Interceptor {
public void before(InvocationInfo invInfo);
public void after(InvocationInfo invInfo);
public void exceptionThrow(InvocationInfo invInfo);
}
MyInterceptor.java拦截器的实现:
package aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MyInterceptor implements Interceptor{
private static Log logger = LogFactory.getLog(MyInterceptor.class);
public void before(InvocationInfo invInfo) {
logger.debug("Pre-processing");
System.out.println("Pre-processing");
System.out.println("beginTransaction");
}
public void after(InvocationInfo invInfo) {
logger.debug("Post-processing");
System.out.println("Post-processing");
System.out.println("endTransaction");
}
public void exceptionThrow(InvocationInfo invInfo) {
logger.debug("Exception-processing");
System.out.println("Exception-processing");
System.out.println("rollback();");
}
}
AOPFactory.java 生成代理类的工厂
package aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AOPFactory {
private static Log logger = LogFactory.getLog(AOPFactory.class);
/**
* 根据类名创建类实例
* @param clzName
* @return
* @throws ClassNotFoundException
*/
public static Object getClassInstance(String clzName){
Class cls;
try {
cls = Class.forName(clzName);
return (Object)cls.newInstance();
} catch (ClassNotFoundException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
} catch (InstantiationException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
} catch (IllegalAccessException e) {
logger.debug(e);
throw new AOPRuntimeException(e);
}
}
/**
* 根据传入的类名,返回AOP代理对象
* @param clzName
* @return
*/
public static Object getAOPProxyedObject(String clzName){
AOPHandler txHandler = new AOPHandler();
Object obj = getClassInstance(clzName);
return txHandler.bind(obj);
}
}
InvocationInfo.java
package aop;
import java.lang.reflect.Method;
public class InvocationInfo {
Object proxy;
Method method;
Object[] args;
Object result;
Throwable Exception;
public InvocationInfo(Object proxy, Method method, Object[] args,
Object result, Throwable exception) {
super();
this.proxy = proxy;
this.method = method;
this.args = args;
this.result = result;
Exception = exception;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public Throwable getException() {
return Exception;
}
public void setException(Throwable exception) {
Exception = exception;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public Object getProxy() {
return proxy;
}
public void setProxy(Object proxy) {
this.proxy = proxy;
}
}
UserDAO.java
需要代理的接口
package aop;
public interface UserDAO {
public void saveUser();
}
UserDAOImp.java
package aop;
public class UserDAOImp implements UserDAO {
public void saveUser() {
// TODO Auto-generated method stub
System.out.println("UserDAOImp saveUser");
}
}
TestAOP.java测试类
package aop;
public class TestAOP {
public static void main(String[] args){
Object ob = AOPFactory.getAOPProxyedObject("aop.UserDAOImp");
UserDAO dao = (UserDAO)ob;
dao.saveUser();
}
}
执行结果:
Invoking Before Intercetpors!
Pre-processing
beginTransaction
Invoking Proxy Method!
UserDAOImp saveUser
Invoking After Method!
Post-processing
endTransaction
显示了代理的效果
CGLib 与Spring AOP
Spring中,引入了CGLib作为无接口情况下的动态代理实现。
CGLib与Dynamic Proxy的代理机制基本类似,只是其动态生成的代理对象并非某个
接口的实现,而是针对目标类扩展的子类。
换句话说,Dynamic Proxy返回的动态代理类,是目标类所实现的接口的另一个实现
版本,它实现了对目标类的代理(如同UserDAOProxy与UserDAOImp的关系)。而CGLib
返回的动态代理类,则是目标代理类的一个子类(代理类扩展了UserDAOImp类)。
引用CGLIB.工程需要导入几个jar包:antlr-2.7.2.jar,asm.jar,asm-attrs.jar,aspectj-1.6.1.jar,aspectjrt.jar,aspectjweaver.jar
AOPInstrumenter.java
package aop;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AOPInstrumenter implements MethodInterceptor{
private static Log logger =
LogFactory.getLog(AOPInstrumenter.class);
private Enhancer enhancer = new Enhancer();
public Object getInstrumentedClass(Class clz) {
enhancer.setSuperclass(clz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(
Object o,
Method method,
Object[] methodParameters,
MethodProxy methodProxy)
throws Throwable {
logger.debug("Before Method =>"+method.getName());
System.out.println("Before Method =>"+method.getName());
Object result = methodProxy.invokeSuper(o, methodParameters);
logger.debug("After Method =>"+method.getName());
System.out.println("After Method =>"+method.getName());
return result;
}
}
UserDAOImp.java
package aop;
public class UserDAOImp {
public void saveUser()
{
System.out.println("UserDAOImp method saveUser");
}
}
TestAOPCGLib.java
package aop;
public class TestAOPCGLib {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
AOPInstrumenter aopInst = new AOPInstrumenter();
UserDAOImp userDAO =
(UserDAOImp) aopInst.getInstrumentedClass(UserDAOImp.class);
userDAO.saveUser();
}
}
TestAOPCGLib的 运行 结果是:
Before Method =>saveUser
UserDAOImp method saveUser
After Method =>saveUser