AOP即面向切面编程,Spring AOP使用纯java实现,不需要专门的编译过程,不需要特殊的类装载器,在运行期通过代理方式向目标类织入增强代码。实现原理有两种:1、java动态代理;2、CGlib动态代理。其中,java动态代理适用实现接口的类,CGlib动态代理则是通过创建子类来实现AOP。
java动态代理:
public class ForumServiceImpl implements ForumService {
public void removeTopic(int topicId) {
//开始对该方法做性能监视
PerformanceMonitor.begin("proxy.ForumServiceImpl.removeTopic");
System.out.println("删除记录"+topicId);
try{
Thread.currentThread().sleep(20);
}catch(Exception e){
throw new RuntimeException(e);
}
//结束对该方法做性能监视
PerformanceMonitor.end;
}
public void removeForum(int forumId) {
//开始对该方法做性能监视
PerMonitor.begin("proxy.ForumServiceImpl.removeForum");
System.out.println("删除记录"+forumId);
try{
Thread.currentThread().sleep(40);
}catch(Exception e){
throw new RuntimeException(e);
}
//结束对该方法做性能监视
PerformanceMonitor.end;
}
}
现在需要做的就是将开始性能监视和结束性能监视的代码从业务类中移除,用AOP来实现。我们将性能监视代码安置在PerformanceHandler中。
//实现InvocationHandler接口
public class PerformanceHandler implements InvocationHandler {
peivate Object target;
//target为目标业务类
public PerformanceHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy,Method method,Object args[])throw Throwable {
PerformanceMonitor.begin(target.getClass().getName()+"."+method.getName());
//通过反射方法调用目标业务类的方法
Object obj = method.invoke(target,args);
PerformanceMonitor.end();
return obj;
}
}
创建代理类实例:
public class Test {
public static void main(String args[]) {
//被代理的目标类
ForumService target = new ForumServiceImpl();
//将目标业务类和横切代码编织到一起
PerformanceHandler handler = new PerformanceHandler(target);
//创建代理实例
ForumService proxy = (ForumService)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);
proxy.removeForum(10);
proxy.removeTopic(1012);
}
}
CGlib动态代理:
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallbanck(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//拦截父类所有方法的调用
public Object intercept(Object obj,Method method,Object args[],MethodProxy proxy) throws Throwable {
PerformanceMonitor.begin(obj.getClass().getName()+"."+method.getName());
//通过代理类调用父类的方法
Object result = proxy.invokeSuper(obj,args);
PerformanceMonitor.end();
return result;
}
}
测试CGlib创建的代理类:
public class Test {
public static void main(String args[]) {
CglibProxy proxy = new CglibProxy();
//通过动态生成子类的方式创建代理类
ForumServiceImpl forumService = (ForumServiceImpl)proxy.getProxy(ForumServiceImpl.class);
forumService.removeForum(10);
forumService.removeTopic(1023);
}
}
CGlib创建的动态代理对象比JDK创建的代理对象性能高出约10倍,但是创建代理对象所需时间大概是JDK的8倍,所以对于单例的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合用CGlib动态代理,反之适用JDK动态代理计数。