两种动态代理:
实现原理:
- JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在用接口调用具体方法前,调用代理类的invoke来处理。
- cglib:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
cglib和JDK对比
- 在jdk6之前,cglib比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
- 在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。
代码实例
JDKd动态代理
public interface IUserManager {
void addUser(String id, String password);
}
public class UserManagerImpl implements IUserManager {
@Override
public void addUser(String id, String password) {
System.out.println("======调用了UserManagerImpl.addUser()方法======");
}
}
public class JdkProxy implements InvocationHandler {
private Object target ;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK动态代理,监听开始!");
Object result = method.invoke(target, args);
System.out.println("JDK动态代理,监听结束!");
return result;
}
private Object getJDKProxy(Object targetObject){
this.target = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}
public static void main(String[] args) {
JdkProxy jdkProxy = new JdkProxy();
UserManager user = (UserManager) jdkProxy.getJDKProxy(new UserManagerImpl());
user.addUser("admin", "123123");
}
}
Cglib动态代理
public class CglibProxy implements MethodInterceptor {
private Object target;
@Override
public Object intercept(Object obj, Method method, Object[] arr, MethodProxy proxy) throws Throwable {
System.out.println("Cglib动态代理,监听开始!");
Object invoke = method.invoke(target, arr);
System.out.println("Cglib动态代理,监听结束!");
return invoke;
}
public Object getCglibProxy(Object objectTarget){
this.target = objectTarget;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(objectTarget.getClass());
enhancer.setCallback(this);
Object result = enhancer.create();
return result;
}
public static void main(String[] args) {
CglibProxy cglib = new CglibProxy();
UserManager user = (UserManager) cglib.getCglibProxy(new UserManagerImpl());
user.delUser("admin");
}
}