AOP 面向方面编程

本文介绍了Spring框架中AOP(面向切面编程)的概念及其动态代理机制的实现原理。通过具体的代码示例展示了如何使用Java Dynamic Proxy和CGLib为类创建动态代理,以及这些代理如何在方法调用前后执行预处理、后处理和异常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

             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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值