代理
jdk动态代理
/**
* jdk动态代理
* @author Administrator
*
*/
public class JDKProxyDemo {
private Object target;//目标类
public JDKProxyDemo(Object target){
this.target=target;
}
/**
* 创建代理类方法
* @param target
* @return
*/
public Object createProxyObject(){
ClassLoader loader=target.getClass().getClassLoader();//目标类类加载器
Class<?>[] interfaces=target.getClass().getInterfaces();//目标类所实现的所有接口
InvocationHandler h=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("jdkProxyDemo");
Object obj = method.invoke(target, args);//对原始操作进行调用(反射)
return obj;
}
};
Object object = Proxy.newProxyInstance(loader, interfaces, h);
return object;
}
}
cglib动态代理
/**
* cglib代理案例
* @author Administrator
*
*/
public class CglibProxyDemo {
private Object target;//目标类
public CglibProxyDemo(Object target){
this.target=target;
}
public Object createProxyObject(){
//1.创建内存中的动态类 Enhancer
//内存中造出一个没有名称的动态类
Enhancer enhancer=new Enhancer();
//2.现在的类最终完成目标类的功能,同时对其进行功能的增强,必须先具有目标类对应的功能————继承
enhancer.setSuperclass(target.getClass());
////3.进行功能的增强
//设置了方法的调用拦截
//设置具体的回调操作
Callback callback = new MethodInterceptor() {
//proxy:代理对象
//method:被拦截的方法对象
//args:调用参数
//methodProxy:
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib");
//Object obj=method.invoke(proxy, args);//这种执行是代理类的方法,而不是目标类的,会造成内存溢出
//以下的两种都是执行目标类的方法
//Object obj = methodProxy.invokeSuper(proxy, args);//执行目标类的方法
Object obj=method.invoke(target, args);
return obj;
}
};
enhancer.setCallback(callback);
return enhancer.create();
}
}
1.jdk动态代理和cglib动态代理的区别
jdk:先有实现接口的类的对象,然后对对象进行代理
cglib:只要有类(无论是否实现接口),对类做代理,简单来说就是对指定的类生成一个子类,覆盖其中的方法(继承)
2.jdk动态代理和cglib动态代理在spring中
(1)当Bean实现接口时,Spring默认使用jdk动态代理
(2)当Bean没有实现接口时,Spring使用cglib动态代理
(3)如果Bean实现接口,也可以强制使用cglib动态代理(在spring配置中加入 `)
3.注意
使用cglib实现动态代理,cglib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,cglib不能对声明为final的方法进行代理,因为cglib原理是动态生成被代理类的子类(被final修饰的类不能被继承)。