JDK动态代理和CGLIB字节码生成的区别?
JDK动态代理只能对实现了接口的类生成代理,而不能针对类;
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。
(1) JDK动态代理实例:
package com.designpatten.proxy;
/**
* Created by lenovo on 2017/11/22.
* 业务接口,提供对外提供的业务功能
*/
public interface UserService {
/**
* 目标方法
*/
void add();
}
package com.designpatten.proxy;
/**
* Created by lenovo on 2017/11/22.
* 业务接口实现类
*/
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("这是业务方法!");
}
}
package com.designpatten.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by lenovo on 2017/11/22.
* 创建自己的InvocationHandler,对业务方法进行增强
*/
public class MyInvocationHandler implements InvocationHandler{
private Object target;
public MyInvocationHandler(Object target){
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("--------before-----------");
//执行目标对象的方法
Object result = method.invoke(target,args);
System.out.println("--------after-----------");
return result;
}
/**
* 获取目标对象的代理对象
* @return
*/
public Object getProxy(){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
}
}
package com.designpatten.proxy;
/**
* Created by lenovo on 2017/11/22.
*/
public class TestProxy {
public static void main(String[] args) {
//实例化目标
UserService userService = new UserServiceImpl();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
//根据目标对象生成代理
UserService proxy =(UserService) myInvocationHandler.getProxy();
proxy.add();
}
}
运行结果:
--------before-----------
这是业务方法!
--------after-----------
(2) CGLIB使用实例:
package com.designpatten.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* Created by lenovo on 2017/11/22.
*/
public class EnhancerDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(EnhancerDemo.class);
enhancer.setCallback(new MethodInterceptorImpl());
EnhancerDemo demo = (EnhancerDemo)enhancer.create();
demo.test();
System.out.println(demo);
}
public void test(){
System.out.println("This is EnhancerDemo Test!");
}
private static class MethodInterceptorImpl implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.err.println("Before invoke"+method);
Object result = methodProxy.invokeSuper(o,objects);
System.err.println("After invoke"+method);
return result;
}
}
}
运行结果:
Before invokepublic void com.designpatten.proxy.EnhancerDemo.test()
This is EnhancerDemo Test!
After invokepublic void com.designpatten.proxy.EnhancerDemo.test()
Before invokepublic java.lang.String java.lang.Object.toString()
Before invokepublic native int java.lang.Object.hashCode()
After invokepublic native int java.lang.Object.hashCode()
After invokepublic java.lang.String java.lang.Object.toString()
[email protected]a67
可以看到在调用System.out.println(test)时,首先调用了toString()方法,然后又调用了hascode(),最后生成了[email protected]这个实例,这个类就是运行时CGLIB产生的。