动态代理和cglib代理
»SpringSpring使用动态代理和动态字节码生成技术(Cglib代理)来实现AOP
目录:
动态代理
代理模式是指在访问者与被访问者之间加入一层代理,从而可以减少被访问者的负担,同时也可以对访问进行一些拦截、过滤等操作。
代理模式是基于接口实现的,即代理与被代理对象必须实现同一接口。代理模式又分为静态代理和动态代理。
静态代理实现过程比较简单,就是代理类和被代理类实现同一接口,代理内部保存有被带理对象的具体实例,外部通过访问代理对象访问被带理对象。
动态代理是指为指定接口在运行期间动态的生成代理对象。动态代理的实现主要由Proxy类和InvocationHandler接口负责
/**
* Request接口
*
* @Author RUANWENJUN
* @Creat 2018-06-05 19:55
*/
public interface MyRequest {
/**
* 发出请求
*/
void request();
}
/**
* 具体请求
* @Author RUANWENJUN
* @Creat 2018-06-05 19:58
*/
public class MyRequestImpl implements MyRequest {
@Override
public void request() {
System.out.println("I want to send a request !!!!");
}
}
/**
* @Author RUANWENJUN
* @Creat 2018-06-05 19:56
*/
public class MyRequestInvocationHandler implements InvocationHandler {
private Object o ;
public MyRequestInvocationHandler(Object o){
this.o = o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("request")){
System.out.println("Hello, I'm Proxy. Time is " + new Date());
}
return method.invoke(o,args);
}
}
**
* @Author RUANWENJUN
* @Creat 2018-06-05 19:59
*/
public class ProxyDemo {
public static void main(String[] args) {
MyRequest myRequest = (MyRequest) Proxy.newProxyInstance(
ProxyDemo.class.getClassLoader(), new Class[]{MyRequest.class},
new MyRequestInvocationHandler(new MyRequestImpl()));
myRequest.request();
}
}
输出:
Hello, I'm Proxy. Time is Tue Jun 05 20:37:59 CST 2018
I want to send a request !!!!
动态代理只能对实现了相应接口的类进行代理。如果一个类没有实现任何接口,那么就不能对其进行代理。
cglib代理
cglib可以为没有实现接口的类进行代理,底层似乎是通过ASM动态修改字节码技术实现的。要使用cglib代理需要导入第三方包
- cglib-3.2.6.jar
- asm-all-6.0_BETA.jar
/**
* @Author RUANWENJUN
* @Creat 2018-06-05 20:09
*/
public class Response {
public void response(){
System.out.println("Hello, I want to send a response. Time is" + new Date());
}
}
/**
* @Author RUANWENJUN
* @Creat 2018-06-05 20:11
*/
public class ResponseCallback implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("response")){
System.out.println("Hello, I am CGLIB");
}
return methodProxy.invokeSuper(o,args);
}
}
/**
* @Author RUANWENJUN
* @Creat 2018-06-05 20:19
*/
public class CglibDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Response.class);
enhancer.setCallback(new ResponseCallback());
Response proxy = (Response) enhancer.create();
proxy.response();
}
}
输出:
Hello, I am CGLIB
Hello, I want to send a response. Time isTue Jun 05 20:42:49 CST 2018
由于cglib是动态创建子类的方式实现代理,所以缺点是不能对final或private方法进行代理。
SpringAOP默认使用动态代理实现,当一个类没有实现接口的时候,会使用cglib代理。Cglib代理所创建的对象性能比jdk动态代理性能高,但是创建时花费的时间也要长。