兩種動態代理:
實現原理:
- 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");
}
}