Spring的两种静态代理:Jdk和Cglib的区别和达成转载
原创1.原则性差异:
java动态代理是使用反射机制生成实现代理接口的匿名类,在调用特定方法之前被调用。InvokeHandler来处理。
而cglib动态代理的用途是asm开放源码包,用于代理对象类。class通过修改其字节码以生成子类来加载和处理该文件。
1如果目标对象实现该接口,则默认情况下将使用它。JDK动态代理实现AOP
2如果目标对象实现该接口,则可以强制其使用该接口。CGLIB实现AOP
3如果目标对象没有实现接口,则必须使用该接口。CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring添加到配置文件
JDK动态代理和CGLIB字节码生成之间的区别是什么?
(1)JDK动态代理只能为实现接口的类生成代理,而不能为类生成代理。
(2)CGLIB它是类的代理,主要是为指定的类生成一个子类,覆盖其中的方法。
因为它是继承,所以最好不要声明类或方法。final
2.代码实现
用户管理界面
package com.lf.shejimoshi.proxy.entity; //用户管理界面 public interface UserManager { //一种新的用户抽象方法 void addUser(String userName,String password); //删除用户抽象方法 void delUser(String userName);
}
用户管理界面实现类
package com.lf.shejimoshi.proxy.entity; //用户管理实施类,实现用户管理界面 public class UserManagerImpl implements UserManager{ //覆盖新的User方法 @Override public void addUser(String userName, String password) { System.out.println("新方法被调用了!"); System.out.println("传入参数为 userName: "+userName+" password: "+password); } //覆盖删除用户方法 @Override public void delUser(String userName) { System.out.println("已调用已删除的方法!"); System.out.println("传入参数为 userName: "+userName); }
}
JDK动态代理
package com.lf.shejimoshi.proxy.jdk;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
import com.lf.shejimoshi.proxy.entity.UserManager; import com.lf.shejimoshi.proxy.entity.UserManagerImpl; //JDK动态代理实现InvocationHandler接口 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){
//对于目标对象target赋值
this.target = targetObject;
//JDK动态代理只能为实现接口的类代理,newProxyInstance 可以看到该函数所需的参数。
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}
public static void main(String[] args) {
JdkProxy jdkProxy = new JdkProxy();//实例化JDKProxy对象
UserManager user = (UserManager) jdkProxy.getJDKProxy(new UserManagerImpl());//获取代理对象
user.addUser("admin", "123123");//执行新方法
}
}
JDK动态代理运行结果
Cglib动态代理(需要导入两个jar包,asm-5.2.jar,cglib-3.2.5.jar。要选择的版本)
package com.lf.shejimoshi.proxy.cglib;
import java.lang.reflect.Method;
import com.lf.shejimoshi.proxy.entity.UserManager; import com.lf.shejimoshi.proxy.entity.UserManagerImpl;
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;
//Cglib动态代理,实现MethodInterceptor接口 public class CglibProxy implements MethodInterceptor { private Object target;//需要代理的目标对象。。
//重写Intercept方法
@Override
public Object intercept(Object obj, Method method, Object[] arr, MethodProxy proxy) throws Throwable {
System.out.println("Cglib动态代理,开始收听!");
Object invoke = method.invoke(target, arr);//方法执行,参数:target 目标对象 arr参数数组
System.out.println("Cglib动态代理,监听结束!");
return invoke;
}
//定义获取代理对象的方法。
public Object getCglibProxy(Object objectTarget){
//对于目标对象target赋值
this.target = objectTarget;
Enhancer enhancer = new Enhancer();
//设置父类,因为Cglib是为指定的类生成一个子类,因此需要指定父类。
enhancer.setSuperclass(objectTarget.getClass());
enhancer.setCallback(this);// 设置回调
Object result = enhancer.create();//创建并返回代理对象。
return result;
}
public static void main(String[] args) {
CglibProxy cglib = new CglibProxy();//实例化CglibProxy对象
UserManager user = (UserManager) cglib.getCglibProxy(new UserManagerImpl());//获取代理对象
user.delUser("admin");//执行删除方法
}
}
Cglib动态代理运行结果
如果您有任何问题,请留言讨论!
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除