JAVA代理,静态,动态详解( 三 )


* h 实现InvocationHandler接口对象
*/
// return Proxy.newProxyInstance(proxyObj.getClass().getClassLoader(),
// proxyObj.getClass().getInterfaces(), new MyInvocationHandler(proxyObj));
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
roxyObj.getClass().getInterfaces(), new MyInvocationHandler(proxyObj));
}
ublic static void main(String[] args) {
ameDao nameDao = (NameDao) getProxy(new NameAndAgeDaoImpl());
AgeDao ageDao = (AgeDao) getProxy(new NameAndAgeDaoImpl());
ameDao.addName("zc");
ageDao.addAge(20);
}
}
思考 为什么需要 实现接口的类,而不是 类
main函数中,运行该语句:
ystem.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
ublic static void main(String[] args) {
ystem.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
ameDao nameDao = (NameDao) getProxy(new NameAndAgeDaoImpl());
AgeDao ageDao = (AgeDao) getProxy(new NameAndAgeDaoImpl());
ameDao.addName("zc");
ageDao.addAge(20);
}
可以查看 $Proxy0 类:
会发现他已经继承了 Proxy , 之后才是创建的一个(多个)接口;而由于java是 单继承、多接口 的特性,所以JDK动态代理,需要实现接口的类 。
CGLib动态代理
CGLIB实现动态代理,并不要求被代理类必须实现接口,底层采用asm字节码生成框架生成代理类字节码(该代理类继承了被代理类) 。
所以被代理类一定不能定义为final class并且对于final 方法不能被代理 。
实现需要
//MethodInterceptor接口的intercept方法
/**
*obj 代理对象
*method 委托类方法,被代理对象的方法字节码对象
*arg 方法参数
*MethodProxy 代理方法MethodProxy对象,每个方法都会对应有这样一个对象
*/
ublic Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy)
Ehancer enhancer = new Enhancer() //Enhancer为字节码增强器,很方便对类进行扩展
enhancer.setSuperClass(被代理类.class);
enhancer.setCallback(实现MethodInterceptor接口的对象)
enhancer.create()//返回代理对象,是被代理类的子类
代码实现
UserDaoImpl 用户实现类(RealSubject)
ublic class UserDaoImpl {
ublic boolean insert(String name) {
ystem.out.println("insert name=" + name);
return true;
}
ublic final boolean insert1(String name) {
ystem.out.println("final insert name=" + name);
return true;
}
}
CglibProxy CGLIB代理类(Proxy)
ublic class CglibProxy implements MethodInterceptor {
[email protected]
ublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
ystem.out.println("——-before——-");
ystem.out.println("Proxy=" + o.getClass());
ystem.out.println("method=" + method);
ystem.out.println("args=" + Arrays.toString(objects));