Spring的两种静态代理:Jdk和Cglib的区别和达成转载

原创
小哥 3年前 (2022-10-27) 阅读数 48 #大杂烩

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动态代理运行结果

如果您有任何问题,请留言讨论!

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门