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
分享到:
相关推荐
### Spring AOP面向方面编程原理详解 #### 一、引言与定义 Spring AOP(Aspect Oriented Programming)是Spring框架中的一个核心组件,用于实现面向切面编程。AOP是一种编程范式,旨在将横切关注点(Cross-cutting...
### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)逐渐暴露出难以应对某些横切关注点(cross-cutting concerns)的问题。为了解决这一挑战,面向方面编程...
面向方面编程(AOP)是一种编程范式,旨在提高软件开发的模块化程度,特别是通过将关注点分离,以便更好地管理复杂系统。AOP的核心概念是“方面”(Aspect),它封装了跨越多个类的横切关注点,如事务管理、日志记录、...
Java Spring AOP(面向方面编程)是Spring框架中的一个重要特性,它允许开发者通过定义切面来模块化横切关注点,如日志、事务管理、性能监控等。这些关注点通常会分散在应用程序的各个部分,AOP提供了一种集中处理...
### AOP面向切面编程详解 #### 一、AOP概览 AOP(Aspect-Oriented Programming,面向切面编程)是一种编程思想和技术,它作为OOP(面向对象编程)的一种补充,主要解决了OOP在处理横切关注点方面的不足。在传统的...
AOP面向切面编程.ppt
面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在提高软件的模块化程度,通过将关注点分离到不同的“切面”中来实现。在.NET环境中,AOP通常通过拦截器(Interceptor)或动态代理...
### 面向方面编程(AOP)详解 #### AOP概述 面向方面编程(Aspect Oriented Programming,简称AOP)是一种程序设计范式,它作为面向对象编程(Object-Oriented Programming,简称OOP)的补充和发展。AOP的核心理念...
面向横截面编程面向横截面编程面向横截面编程面向横截面编程面向横截面编程
本教程介绍 AOP 及其基本概念。AOP 及其相关的工具使您可以将基本横切关注点(如日志记录和安全)的代码,与程序的核心应用逻辑相分离。AOP 通过使代码更具有可读性、更不容易出错以及更容易设计和维护,改善了代码...
面向方面编程(AOP,Aspect-Oriented Programming)是一种编程范式,旨在解决传统面向对象编程(OOP)中横切关注点的问题。横切关注点是指那些跨越多个对象或模块,但又不直接属于单一模块职责的功能,如日志记录、...
aop面向切面编程教学ppt
### 面向方面编程(AOP)介绍 #### 一、面向方面编程产生的背景 在软件开发领域,面向对象编程(OOP)是长期以来的主要编程范式之一。然而,在实际的软件开发过程中,经常会遇到一些跨越多个类或模块的关注点,如...
面向切面编程(Aspect-Oriented Programming,AOP)是Spring框架的核心特性之一,它提供了一种优雅的方式来处理系统的横切关注点,如日志、事务管理、性能监控和权限控制等。在Spring中,AOP主要通过代理模式实现,...
在这一阶段,程序员们开始意识到将程序分解为一系列独立的功能模块或方法的重要性,但尚未发展出如面向切面编程(Aspect-Oriented Programming,AOP)等更为先进的技术。 在面向方法编程的“原始时代”,开发者主要...
spect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的...
面向切面编程(AOP)是一种编程范式,它旨在将关注点分离,使得系统中的核心业务逻辑与系统服务(如日志、事务管理、权限控制等)可以解耦。在Android开发中,AOP的应用可以帮助我们更好地组织代码,提高可维护性和...
在Java世界里,Spring框架是应用最广泛的轻量级框架之一,它的核心特性包括IOC(Inversion of Control,反转控制)和AOP(Aspect Oriented Programming,面向方面编程)。这两个概念是Spring框架的灵魂,极大地提升...
是一个 PHP 5.4 库,让 PHP 支持 AOP 面向方面编程方法,无需 PECL 扩展、Runkit、evals 或者 DI 容器支持。可使用 XDebug 轻松调试。 示例代码: // Aspect/MonitorAspect.php namespace Aspect; use Go\...