发布时间:2023-03-16 18:30
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
/**
* 用户管理接口
*/
public interface IUserManager {
void addUser(User user);
void delUser(Long userId);
}
/**
* 管理类的实现
*/
public class UserManagerImpl implements IUserManager {
@Override
public void addUser(User user) {
System.out.println("执行了添加用户方法:"+user);
}
@Override
public void delUser(Long userId) {
System.out.println("执行了删除用户方法:"+userId);
}
}
@Slf4j
//jdk动动态代理,需要实现接口[InvocationHandler]
public class JdkProxy implements InvocationHandler {
private Object target;// 需要我们进行代理的目标对象
// 调用方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("jdk动态代理,监听ing....");
// 执行代理后的方法,传入参数,获得执行结果,将结果返回
Object result = method.invoke(target, args);
log.info("jdk动态代理,监听end....");
return result;
}
/**
* 准备一个获取代理对象的方法
* @param targetObject 需要把对象转为代理对象的原对象
* @return 代理对象
*/
private Object getJDKProxy(Object targetObject){
// 将传入的对象写入本类的目标对象
this.target=targetObject;
// JDK动态代理只能针对实现了接口的类进行代理,newProxyInstance 函数所需参数就可看出
//参数,需要实例化的对象的class的加载器,需要实例化的对象的接口,以及实现了InvocationHandler的类(本类)
Object proxyInstance = Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
log.info("获取到了实例化对象:{}",proxyInstance);
return proxyInstance;
}
// 测试方法
public static void main(String[] args) {
// 先实例化JdkProxy对象,就是我们实现了InvocationHandler的对象,通过他来创建代理对象
JdkProxy jdkProxy = new JdkProxy();
// 传入我们需要代理的对象,获取代理对象,转型为实现类的接口,然后我们就能够通过接口进行调用
IUserManager proxyObject = (IUserManager)jdkProxy.getJDKProxy(new UserManagerImpl());
// 调用方法
proxyObject.addUser(new User(1982L,"Kira"));
}
}
JDK动态代理只能针对实现了接口的类进行代理,newProxyInstance 函数所需参数就可看出
@Slf4j
//Cglib动态代理,实现MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {
private Object target;
//重写拦截方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
log.info("cglib动态代理,监听ing....");
Object invoke = method.invoke(target, objects);//方法执行,参数:target 目标对象 objects参数数组
log.info("cglib动态代理,监听end....");
return invoke;
}
// 定义获取代理对象的方法
public Object getCglibProxy(Object objectTarget){
// 给成员中的目标对象赋值
this.target=objectTarget;
Enhancer enhancer = new Enhancer();
//设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
enhancer.setSuperclass(target.getClass());
// 设置回调
enhancer.setCallback(this);
// 创建代理对象
Object result = enhancer.create();
log.info("获取到了实例化对象:{}",result);
return result;
}
// 调用测试
public static void main(String[] args) {
// 创建cglib代理对象
CglibProxy cglibProxy = new CglibProxy();
log.info("接口调用");
// 获取代理对象。由于这里是直接生成了一个确实的实体类,我们依然会把他转型成他的接口类进行调用
IUserManager userManage =(IUserManager) cglibProxy.getCglibProxy(new UserManagerImpl());
userManage.delUser(12865L);
// 由于是生成了一个子类,所以使用子类型调用也可以
UserManagerImpl userManageImpl =(UserManagerImpl) cglibProxy.getCglibProxy(new UserManagerImpl());
userManageImpl.addUser(new User(12312L,"法外狂徒张三"));
log.info("子类调用");
}
}
Demo是做出来了。。。但是不知道能干啥。。。。
执行步骤:
1.创建代理类对象,
2.将传入的实现设置进成员变量,重写的方法中调用成员变量实现类的方法,然后使用Proxy.newProxyInstance
创建代理实例化对象返回;
3.获得代理对象以后可以调用执行
被spring惯坏了吗。。。。
之前好像是:
1.在类里注入接口,然后方法调用接口的抽象方法就可以了;
2.创建类的时候通过各种构造指定上面注入接口的具体实现
,然后实现可以动态的变更;