您的位置:首页 > 运维架构

AOP动态代理织入

2017-09-20 17:15 190 查看
在之前一篇中,我们介绍了什么是AOP面向切面编程。下面以Spring AOP 为例来详细讲解。

Spring AOP 采用的是动态代理织入

代理是实现AOP的底层技术。

下面介绍两种代理技术:

1. JDK代理技术

2. CGlib代理技术

JDK代理:

InvocationHandler 是一个接口,增强逻辑代码就是放在这个接口的实现类中。

代理类= 目标类 + 增强逻辑。相当于一个新类。

package com.smart.proxy;

import java.lang.reflect.InvocationHandler; //相当于一个编织器,将切面织入目标类
import java.lang.reflect.Method;

public class PerformaceHandler implements InvocationHandler {
private Object target;  //目标类
public PerformaceHandler(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
PerformanceMonitor.begin(target.getClass().getName()+"."+ method.getName());//逻辑代码
Object obj = method.invoke(target, args);//反射调用目标对象的方法
PerformanceMonitor.end();//横切逻辑代码
return obj;
}
}


PerformaceHander 为一个编织器对象

@Test
public void proxy() {
// 业务类正常编码的测试
// ForumService forumService = new ForumServiceImpl();
// forumService.removeForum(10);
// forumService.removeTopic(1012);
// 使用JDK动态代理
ForumService target = new ForumServiceImpl();//目标类
PerformaceHandler handler = new PerformaceHandler(target);//编织器类,在目标类中织入相应的代码逻辑
ForumService proxy = (ForumService) Proxy.newProxyInstance(target
.getClass().getClassLoader(),
target.getClass().getInterfaces(), handler);//生成代理
proxy.removeForum(10); // 按照目标类所显现接口来调用方法。(可以理解为接口的代理)
proxy.removeTopic(1012);


proxy 通过静态方法,par1 为目标类的类加载器,par2为目标类的借口,par3位编织器对象。这样就生成了一个目标类增强后的代理类。proxy.调用代理对象的方法时,就会去执行invoke函数。从而实现代码注入

对于没有通过借口定义业务方法的类,我们就必须使用CGlib来操作。CGlib 采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有的父类方法,并顺势织入横切逻辑。

package com.smart.proxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {//相当于一个代理创建器支持所有类
private Enhancer enhancer = new Enhancer();

public Object getProxy(Class clazz) { //获得代理类
enhancer.setSuperclass(clazz); //设置目标类
enhancer.setCallback(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;
}
}


下面看测试:

@Test
public void proxy() {
//使用CGLib动态代理
CglibProxy cglibProxy = new CglibProxy(); //获取代理创建器
ForumService forumService = (ForumService)cglibProxy.getProxy(ForumServiceImpl.class);//获取代理向上转型
forumService.removeForum(10);//父类方法调用,会被intercept拦截,织入增加。
forumService.removeTopic(1023);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  aop 动态代理 spring