目前整个开发社区对AOP(Aspect Oriented Programing)推崇备至
![](/icons/94009dou.gif)
也涌现出大量支持AOP
![](/icons/94009de.gif)
优秀Framework,--Spring, JAC, Jboss AOP 等等
![](/icons/94009dou2.gif)
AOP似乎
![](/icons/94009yi.gif)
时的间成了潮流
![](/icons/94009dou2.gif)
Java初学者不禁要发出感慨
![](/icons/94009dou.gif)
OOP还没有学通呢
![](/icons/94009dou.gif)
又来AOP
![](/icons/94009dou2.gif)
本文不是要在理论上具体阐述何为AOP, 为何要进行AOP . 要详细了解学习AOP可以到它老家http://aosd.net去瞧瞧
![](/icons/94009dou2.gif)
这里只是意图通过
![](/icons/94009yi.gif)
个简单
![](/icons/94009de.gif)
例子向初学者展示
![](/icons/94009yi.gif)
下如何来进行AOP.
为了简单起见
![](/icons/94009dou.gif)
例子没有没有使用任何第 3方
![](/icons/94009de.gif)
AOP Framework, 而是利用Java语言本身自带
![](/icons/94009de.gif)
动态代理功能来实现AOP.
让我们先回到AOP本身
![](/icons/94009dou.gif)
AOP主要应用于日志记录
![](/icons/94009dou.gif)
性能统计
![](/icons/94009dou.gif)
安全控制,事务处理等方面
![](/icons/94009dou2.gif)
它
![](/icons/94009de.gif)
主要意图就要将日志记录
![](/icons/94009dou.gif)
性能统计
![](/icons/94009dou.gif)
安全控制等等代码从商业逻辑代码中清楚
![](/icons/94009de.gif)
划分出来
![](/icons/94009dou.gif)
我们可以把这些行为
![](/icons/94009yi.gif)
个
![](/icons/94009yi.gif)
个单独看作系统所要解决
![](/icons/94009de.gif)
问题
![](/icons/94009dou.gif)
就是所谓
![](/icons/94009de.gif)
面向问题
![](/icons/94009de.gif)
编程(不知将AOP译作面向问题
![](/icons/94009de.gif)
编程是否欠妥)
![](/icons/94009dou2.gif)
通过对这些行为
![](/icons/94009de.gif)
分离
![](/icons/94009dou.gif)
我们希望可以将它们独立地配置到商业思路方法中
![](/icons/94009dou.gif)
而要改变这些行为也不需要影响到商业思路方法代码
![](/icons/94009dou2.gif)
假设系统由
![](/icons/94009yi.gif)
系列
![](/icons/94009de.gif)
BusinessObject所完成业务逻辑功能
![](/icons/94009dou.gif)
系统要求在每
![](/icons/94009yi.gif)
次业务逻辑处理时要做日志记录
![](/icons/94009dou2.gif)
这里我们略去具体
![](/icons/94009de.gif)
业务逻辑代码
![](/icons/94009dou2.gif)
public
![](/icons/94009int.gif)
erface BusinessInterface {
public void processBusiness
![](/icons/94009kh.gif)
;
}
public
![](/icons/94009class.gif)
BusinessObject implements BusinessInterface {
private Logger logger = Logger.getLogger(this.getClass
![](/icons/94009kh.gif)
.getName
![](/icons/94009kh.gif)
);
public void processBusiness
![](/icons/94009kh.gif)
{
try {
logger.info("start to processing...");
//business logic here.
![](/icons/94009System.gif)
.out.pr
![](/icons/94009int.gif)
ln(“here is business logic”);
logger.info("end processing...");
} catch (Exception e){
logger.info("exception happends...");
//exception handling
}
}
}
这里处理商业逻辑
![](/icons/94009de.gif)
代码和日志记录代码混合在
![](/icons/94009yi.gif)
起
![](/icons/94009dou.gif)
这给日后
![](/icons/94009de.gif)
维护带来
![](/icons/94009yi.gif)
定
![](/icons/94009de.gif)
困难
![](/icons/94009dou.gif)
并且也会造成大量
![](/icons/94009de.gif)
代码重复
![](/icons/94009dou2.gif)
完全相同
![](/icons/94009de.gif)
log代码将出现在系统
![](/icons/94009de.gif)
每
![](/icons/94009yi.gif)
个BusinessObject中
![](/icons/94009dou2.gif)
按照AOP
![](/icons/94009de.gif)
思想
![](/icons/94009dou.gif)
我们应该把日志记录代码分离出来
![](/icons/94009dou2.gif)
要将这些代码分离就涉及到
![](/icons/94009yi.gif)
个问题
![](/icons/94009dou.gif)
我们必须知道商业逻辑代码何时被
![](/icons/94009diaoyong.gif)
![](/icons/94009dou.gif)
这样我们好插入日志记录代码
![](/icons/94009dou2.gif)
![](/icons/94009yi.gif)
般来说要截获
![](/icons/94009yi.gif)
个思路方法
![](/icons/94009dou.gif)
我们可以采用回调思路方法或者动态代理
![](/icons/94009dou2.gif)
动态代理
![](/icons/94009yi.gif)
般要更加灵活
![](/icons/94009yi.gif)
些
![](/icons/94009dou.gif)
目前多数
![](/icons/94009de.gif)
AOP Framework也大都采用了动态代理来实现
![](/icons/94009dou2.gif)
这里我们也采用动态代理作为例子
![](/icons/94009dou2.gif)
JDK1.2以后提供了动态代理
![](/icons/94009de.gif)
支持
![](/icons/94009dou.gif)
![](/icons/94009chengxu.gif)
员通过实现java.lang.reflect.InvocationHandler接口提供
![](/icons/94009yi.gif)
个执行处理器
![](/icons/94009dou.gif)
然后通过java.lang.reflect.Proxy得到
![](/icons/94009yi.gif)
个代理对象
![](/icons/94009dou.gif)
通过这个代理对象来执行商业思路方法,在商业思路方法被
![](/icons/94009diaoyong.gif)
![](/icons/94009de.gif)
同时
![](/icons/94009dou.gif)
执行处理器会被自动
![](/icons/94009diaoyong.gif)
![](/icons/94009dou2.gif)
有了JDK
![](/icons/94009de.gif)
这种支持
![](/icons/94009dou.gif)
我们所要做
![](/icons/94009de.gif)
仅仅是提供
![](/icons/94009yi.gif)
个日志处理器
![](/icons/94009dou2.gif)
public
![](/icons/94009class.gif)
LogHandler implements InvocationHandler {
private Logger logger = Logger.getLogger(this.getClass
![](/icons/94009kh.gif)
.getName
![](/icons/94009kh.gif)
);
private Object delegate;
public LogHandler(Object delegate){
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object
![](/icons/94009zhk2.gif)
args) throws Throwable {
Object o = null;
try {
logger.info("method stats..." + method);
o = method.invoke(delegate,args);
logger.info("method ends..." + method);
} catch (Exception e){
logger.info("Exception happends...");
//excetpion handling.
}
![](/icons/94009return.gif)
o;
}
}
现在我们可以把BusinessObject里面
![](/icons/94009de.gif)
所有日志处理代码全部去掉了
![](/icons/94009dou2.gif)
public
![](/icons/94009class.gif)
BusinessObject implements BusinessInterface {
private Logger logger = Logger.getLogger(this.getClass
![](/icons/94009kh.gif)
.getName
![](/icons/94009kh.gif)
);
public void processBusiness
![](/icons/94009kh.gif)
{
//business processing
![](/icons/94009System.gif)
.out.pr
![](/icons/94009int.gif)
ln(“here is business logic”);
}
}
客户端
![](/icons/94009diaoyong.gif)
商业思路方法
![](/icons/94009de.gif)
代码如下:
BusinessInterface businessImp =
![](/icons/94009new.gif)
BusinessObject
![](/icons/94009kh.gif)
;
InvocationHandler handler =
![](/icons/94009new.gif)
LogHandler(businessImp);
BusinessInterface proxy = (BusinessInterface) Proxy.
![](/icons/94009new.gif)
ProxyInstance(
businessImp.getClass
![](/icons/94009kh.gif)
.getClassLoader
![](/icons/94009kh.gif)
,
businessImp.getClass
![](/icons/94009kh.gif)
.getInterfaces
![](/icons/94009kh.gif)
,
handler);
proxy.processBusiness
![](/icons/94009kh.gif)
;
![](/icons/94009chengxu.gif)
输出如下:
INFO: method stats...
here is business logic
INFO: method ends...
至此我们
![](/icons/94009de.gif)
第
![](/icons/94009yi.gif)
次小尝试算是完成了
![](/icons/94009dou2.gif)
可以看到
![](/icons/94009dou.gif)
采用AOP的后
![](/icons/94009dou.gif)
日志记录和业务逻辑代码完全分开了
![](/icons/94009dou.gif)
以后要改变日志记录
![](/icons/94009de.gif)
话只需要修改日志记录处理器就行了
![](/icons/94009dou.gif)
而业务对象本身(BusinessObject)无需做任何修改
![](/icons/94009dou2.gif)
并且这个日志记录不会造成重复代码了
![](/icons/94009dou.gif)
所有
![](/icons/94009de.gif)
商业处理对象都可以重用这个日志处理器
![](/icons/94009dou2.gif)
当然在实际应用中
![](/icons/94009dou.gif)
这个例子就显得太粗糙了
![](/icons/94009dou2.gif)
由于JDK
![](/icons/94009de.gif)
动态代理并没有直接支持
![](/icons/94009yi.gif)
次注册多个InvocationHandler
![](/icons/94009dou.gif)
那么我们对业务处理思路方法既要日志记录又要性能统计时
![](/icons/94009dou.gif)
就需要自己做
![](/icons/94009yi.gif)
些变通了
![](/icons/94009dou2.gif)
![](/icons/94009yi.gif)
般我们可以自己定义
![](/icons/94009yi.gif)
个Handler接口
![](/icons/94009dou.gif)
然后维护
![](/icons/94009yi.gif)
个队列存放所有Handler, 当InvocationHandler被触发
![](/icons/94009de.gif)
时候我们依次
![](/icons/94009diaoyong.gif)
自己
![](/icons/94009de.gif)
Handler
![](/icons/94009dou2.gif)
所幸
![](/icons/94009de.gif)
是目前几乎所有
![](/icons/94009de.gif)
AOP Framework都对这方面提供了很好
![](/icons/94009de.gif)
支持.这里推荐大家使用Spring