// 未分类
简单aop模块(cglib实现)
发布 2018-09-30 · 永久链接
no excerpt about this article
使用cglib实现简单的aop模块
**around还有些问题。**
#### jar包
需要jar包`cglib-nodep-2.1_3`,或者 maven 加上
``` xml
cglib
cglib
3.2.4
```
版本视情况改变。
#### 目标类
假设有这么个目标类型
``` java
public class TestTarget {
public void out(String a) {
System.out.println("Target out."+a);
}
}
```
TestTarget类里面有个`out`方法,我们希望在`out`方法执行的时候打log。
#### 增强器
增强器Enhancer可以增强原有的方法,并返回一个新的对象。
``` java
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestTarget.class);
enhancer.setCallback(callback);
```
代码创建一个enhancer,然后把一个`Class` 对象传进去,enhancer对它干了什么,暂时不用理。
随后传入一个callback,callback是这样的:
``` java
public class BeforeCallBack implements MethodInterceptor {
public BeforeCallBack() {
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// do something here.
return methodProxy.invokeSuper(o, objects);
}
}
```
`BeforeCallBack`实现了`MethodInterceptor`接口。这里才是真正的增强,在return原有的方法之前,执行一些东西(这里是before切点,也可以改成after、around)
**效果**:
此处匿名内部类实现的接口并替换成lambda。
``` java
public class MainClass {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestTarget.class);
enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("before.");
return methodProxy.invokeSuper(o,objects);
});
TestTarget testTarget = (TestTarget) enhancer.create();
testTarget.out();
}
}
class TestTarget{
public void out(){
System.out.println("out. ");
}
}
```
---
``` bash
before.
out.
```
#### 通用化
* 切点
在增强的时候,我们并没有指定是哪一个方法被增强,所以类里面的所有方法都会被起作用。
cglib提供了`CallbackFilter`来区分什么方法应该使用什么Callback(before、after..etc)来处理。
用来标记方法类型的,注解`@interface`无疑是最合适的了。
* 切面
我们在拦截了方法之后,在它返回前后进行一些操作,在`intercept`方法里边写上我们要有的操作。
也就是说,每有一个Callback的需求,我们都要手动的实现接口并且加上业务代码。那么我们应该把业务代码抽取出来。
**把业务抽象成一个切面**,比如打log,我们有个LogAspect,继承于AbstractAspect,届时,只要在`intercept`跑抽象的方法就可以了。
比如:
``` java
public class BeforeCallBack implements MethodInterceptor {
Class extends AbstractAspect> aspect;
public BeforeCallBack(Class extends AbstractAspect> aspect) {
this.aspect = aspect;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
AbstractAspect instance = aspect.newInstance();
instance.doBefore();
return methodProxy.invokeSuper(o, objects);
}
}
```
不管实际上的切面是什么,他都是`AbstractAspect`。
* 注解解析
主要的注解有两个:`Aspect`、`PointCut`,一个是用于标记TargetClass要应用什么切面,一个是用于标记方法的切点类型(before、after..)
#### demo
[gitee demo](https://gitee.com/someonedeng/DAop.git)