AOP学习笔记
概 念
1. 切面(Aspect)
切面,对象操作过程中的截面。这可能是AOP中最关键的一个术语。
我们首先来看一个应用开发中常见的切面:用户权限检查。大概只要是完整的应用,都
少不了用户权限检查这个模块,不同身份的用户可以做什么,不可以做什么,均由这个模块
加以判定。 而这个模块调用的位置通常也比较固定:用户发起请求之后, 执行业务逻辑之前。
针对权限检查这一模块进行分离,我们就得到了一个切面.
切面意义何在?
首先根据上例,假设我们实现了一个通用的权限检查模块,那么就可以在这层切面上进
行统一的集中式权限管理。而业务逻辑组件则无需关心权限方面的问题。也就是说,通过切
面,我们可以将系统中各个不同层次上的问题隔离开来,实现统一集约式处理。各切面只需
集中于自己领域内的逻辑实现。
这一方面使得开发逻辑更加清晰,专业化分工更加易于进行;另一方面,由于切面的隔
离,降低了耦合性,我们就可以在不同的应用中将各个切面组合使用,从而使得代码可重用
性大大增强。
2连接点(JoinPoint)
程序运行过程中的某个阶段点。如某个方法调用,或者某个异常被抛出。
3.处理逻辑(Advice)
在某个连接点所采用的处理逻辑
处理逻辑的调用模式通常有三种:
i. Around
在连接点前后插入预处理过程和后处理过程。
ii. Before
仅在连接点之前插入预处理过程。
iii. Throw
在连接点抛出异常时进行异常处理。
4.切点(PointCut)
一系列连接点的集合,它指明处理方式(Advice)将在何时被触发。
Dynamic Proxy 与Spring AOP
Dynamic Proxy是JDK 1.3版本中新引入的一种动态代理机制。它是Proxy模式的一
种动态实现版本。
代码:
public class TxHandler implements InvocationHandler {
private Object originalObject;
public Object bind(Object obj) {
this.originalObject = obj;
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
if (!method.getName().startsWith("save")) {
UserTransaction tx = null;
try {
tx = (UserTransaction) (
new InitialContext().lookup("java/tx")
);
result = method.invoke(originalObject, args);
tx.commit();
} catch (Exception ex) {
if (null != tx) {
try {
tx.rollback();
} catch (Exception e) {
}
}
}
} else {
result = method.invoke(originalObject, args);
}
return result;
}
}
在示例代码中,我们为所有名称以“save”开头的方法追加了JTA事务管理。
下面是夏昕老师在客户培训过程中编写的一个Dynamic Proxy based AOP实现示例,非常简单,有兴趣的读者可以看看。
1、AOPHandler .java
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!");
invokeInterceptorsBefore(invInfo);
try {
logger.debug("Invoking Proxy Method!");
result = method.invoke(originalObject, args);
invInfo.setResult(result);
logger.debug("Invoking After Method!");
invokeInterceptorsAfter(invInfo);
} catch (Throwable tr) {
invInfo.setException(tr);
logger.debug("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);
}
}
}
2、Interceptor .java:
public interface Interceptor {
public void before(InvocationInfo invInfo);
public void after(InvocationInfo invInfo);
public void exceptionThrow(InvocationInfo invInfo);
}
3、InvocationInfo.java:
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;
}
}
4、AOPFactory.java
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);
}
}
5、MyInterceptor .java
public class MyInterceptor implements Interceptor{
private static Log logger = LogFactory.getLog(MyInterceptor.class);
public void before(InvocationInfo invInfo) {
logger.debug("Pre-processing");
}
public void after(InvocationInfo invInfo) {
logger.debug("Post-processing");
}
public void exceptionThrow(InvocationInfo invInfo) {
logger.debug("Exception-processing");
}
}
posted on 2009-03-25 11:09
重庆理工小子 阅读(315)
评论(0) 编辑 收藏 所属分类:
Spring2