做网站用什么颜色好,做图片视频的网站有哪些,一个门户网站多少钱,洗发水营销推广软文800字面对新鲜事物#xff0c;我们要先了解在去探索事物的本质-默 目录
一.介绍二者代理模式
1.1.Jdk代理模式
1.2cglib代理模式
1.3二者区别
1.3.1有无接口
1.3.2灵活性
1.4对于两种代理模式的总结
1.4.1jdk代理模式
1.4.2cglib代理模式
二.两种代理模式应用场景
2.1jd… 面对新鲜事物我们要先了解在去探索事物的本质-默 目录
一.介绍二者代理模式
1.1.Jdk代理模式
1.2cglib代理模式
1.3二者区别
1.3.1有无接口
1.3.2灵活性
1.4对于两种代理模式的总结
1.4.1jdk代理模式
1.4.2cglib代理模式
二.两种代理模式应用场景
2.1jdk代理模式应用场景
2.1.1基于接口的代理
2.1.2细粒度的方法拦截
2.2cglib代理模式应用场景
2.2.1非基于接口的代理
2.2.2覆盖父类中的方法
2.2.3高性能的代理
三.代码演示
3.1jdk代理模式
3.1.1源码 3.2思路解释
3.2cglib代理模式
3.2.1源码 3.2.1思路解释 一.介绍二者代理模式
1.1.Jdk代理模式 JDK代理是通过接口实现的动态代理方式。当目标类实现了至少一个接口时Spring AOP会使用JDK代理。JDK代理通过在运行时创建一个实现了目标接口的代理类来实现代理功能。代理对象和目标对象实现了同一个接口因此只能代理接口中定义的方法。 1.2cglib代理模式 CGLIB代理是通过继承实现的动态代理方式。当目标类没有实现任何接口时Spring AOP会使用CGLIB代理。CGLIB代理通过在运行时创建目标类的子类来实现代理功能。代理对象继承自目标对象并覆盖了目标对象的非final方法因此可以代理目标对象的所有方法。 1.3二者区别
1.3.1有无接口 JDK代理要求目标类必须实现接口而CGLIB代理不需要可以代理普通的Java类。 1.3.2灵活性 JDK代理基于接口适用于对接口的代理更加灵活但无法代理没有接口的类。 CGLIB代理是通过生成目标类的子类来实现代理适用于对类的代理。CGLIB代理具有更高的性能因为它不需要通过反射调用目标对象的方法。 1.4对于两种代理模式的总结
1.4.1jdk代理模式
JDK 动态代理是基于接口的代理方式。它通过创建一个实现了目标接口的代理类并在代理类中实现代理逻辑。代理类在运行时动态生成并在其中调用原始对象的方法
JDK 动态代理通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现。代理对象是在运行时动态生成的。
无法代理非公有类JDK 动态代理不能代理那些声明为 final 的类因为 final 类不能被继承。另外由于代理类是在运行时动态生成的因此也无法代理那些没有默认构造函数的类。
方法拦截代理对象在调用方法时会将方法调用转发给 InvocationHandler 的实现类在这个实现类中可以添加自定义的逻辑完成方法的拦截、增强等操作。
性能相对较低相比于 CGLIB 动态代理JDK 动态代理的性能较低。这主要是因为 JDK 动态代理需要通过反射来调用目标对象的方法。
总的来说JDK 动态代理是一种比较常用的代理方式适用于代理接口的场景易于使用和理解。但它的局限性在于只能代理实现了接口的类并且在性能方面稍逊于 CGLIB 动态代理。
1.4.2cglib代理模式 CGLIB 动态代理是一种基于继承的代理方式。它通过创建目标类的子类来实现代理。代理类继承自目标类并重写其中的方法在重写的方法中添加了增强逻辑。 类代理CGLIB 动态代理可以代理类无论是否实现了接口。这使得它可以代理那些没有实现接口的类不包括 final 类。
代理生成CGLIB 动态代理使用字节码生成库来创建目标类的子类。代理类在运行时动态生成并且不需要目标类实现任何接口。
方法拦截被代理的方法在执行时会调用代理类中的方法。这样我们可以在代理类中添加拦截器MethodInterceptor并在拦截器中实现自定义的逻辑。
性能相对较高相比于 JDK 动态代理CGLIB 动态代理的性能更高。这是因为 CGLIB 通过继承来实现代理避免了反射调用的开销。
对于 final 方法和私有方法的限制CGLIB 默认无法代理 final 方法因为 final 方法无法被重写。此外CGLIB 也不能代理私有方法因为代理类无法访问目标类的私有方法。但是可以通过设置 CGLIB 的 Enhancer 对象的 setUseReflection(true) 方法来强制代理私有方法。这样一来CGLIB 将使用反射调用私有方法但这可能会导致性能下降。
需要注意的是CGLIB 代理依赖于字节码生成在代理类生成时会占用一定的时间和内存。
总结来说CGLIB 动态代理适用于代理类的场景可以代理没有实现接口的类并且具有较高的性能。
二.两种代理模式应用场景
2.1jdk代理模式应用场景
2.1.1基于接口的代理 如果目标对象实现了接口可以使用JDK动态代理。它要求目标对象实现一个接口并且生成的代理对象也会实现相同的接口。 2.1.2细粒度的方法拦截 JDK动态代理可以在目标对象的方法调用前后添加额外的逻辑。例如在方法调用前打印日志、进行权限验证或事务管理等 2.2cglib代理模式应用场景
2.2.1非基于接口的代理 CGLIB动态代理可以代理没有实现接口的类。因此当目标对象没有实现任何接口时可以使用CGLIB动态代理。 2.2.2覆盖父类中的方法 CGLIB动态代理通过继承目标类并覆盖其中的方法来创建代理对象。这使得它可以代理目标类中的非公有方法。 2.2.3高性能的代理 相比JDK动态代理CGLIB动态代理通常具有更高的性能因为它直接操作字节码而不需要通过反射调用方法。 三.代码演示
3.1jdk代理模式
3.1.1源码
package com.daili.jdk;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** author lz* create 2023-08-21 9:33*/
public interface UserService {void saveUser(String username);
}
class UserServiceImpl implements UserService {public void saveUser(String username) {System.out.println(Saving user: username);}
}class UserServiceProxy implements InvocationHandler {private Object target;public UserServiceProxy(Object target) {this.target target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(Before method: method.getName());Object result method.invoke(target, args);System.out.println(After method: method.getName());return result;}
}class Main {public static void main(String[] args) {UserService userService new UserServiceImpl();UserService proxy (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new UserServiceProxy(userService));proxy.saveUser(刘兵);}
} 3.2思路解释
定义了一个接口 UserService其中包含了一个抽象方法 saveUser(String username)。实现了接口 UserService 的具体类 UserServiceImpl该类实现了 saveUser 方法用于保存用户信息。创建了一个代理类 UserServiceProxy实现了 InvocationHandler 接口。在 invoke 方法中对目标方法进行前置和后置处理即在目标方法执行前输出 Before method: 方法名在目标方法执行后输出 After method: 方法名。在 Main 类的 main 方法中创建了一个 UserServiceImpl 的实例。通过 Proxy.newProxyInstance() 方法创建代理对象传入目标对象的类加载器、接口数组和 UserServiceProxy 的实例。返回的代理对象将会实现 UserService 接口。调用代理对象的 saveUser(John) 方法实际上会触发代理对象的 invoke 方法从而实现了动态代理。
在代码执行过程中代理对象的 invoke 方法会先输出 Before method: saveUser然后调用目标对象的 saveUser 方法最后输出 After method: saveUser。
通过 JDK 动态代理可以在不修改目标对象代码的情况下对其方法进行增强、添加日志等操作。
3.2cglib代理模式
3.2.1源码
package com.daili.cglib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** author lz* create 2023-08-21 9:49*/
public class UserService {public void saveUser(String username) {System.out.println(Saving user: username);}
}
class UserServiceInterceptor implements MethodInterceptor {Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(Before method: method.getName());Object result proxy.invokeSuper(obj, args);System.out.println(After method: method.getName());return result;}static class Main {public static void main(String[] args) {Enhancer enhancer new Enhancer();enhancer.setSuperclass(UserService.class);enhancer.setCallback(new UserServiceInterceptor());UserService proxy (UserService) enhancer.create();proxy.saveUser(刘兵);}
}
}3.2.1思路解释
定义了一个类 UserService其中包含了一个方法 saveUser(String username)用于保存用户信息。创建了一个代理类 UserServiceInterceptor实现了 MethodInterceptor 接口。在 intercept 方法中对目标方法进行前置和后置处理即在目标方法执行前输出 Before method: 方法名在目标方法执行后输出 After method: 方法名。使用 MethodProxy 对象调用原始方法。在 Main 类的 main 方法中创建了一个 Enhancer 对象。通过 enhancer.setSuperclass(UserService.class) 设置目标类为 UserService。通过 enhancer.setCallback(new UserServiceInterceptor()) 设置回调处理器为 UserServiceInterceptor 的实例。调用 enhancer.create() 方法返回代理对象将其转换为 UserService 类型。调用代理对象的 saveUser(John) 方法会触发代理对象的 intercept 方法从而实现了动态代理。
在代码执行过程中代理对象的 intercept 方法会先输出 Before method: saveUser然后调用目标对象的 saveUser 方法最后输出 After method: saveUser。
通过 CGLIB 动态代理可以在不修改目标对象代码的情况下对其方法进行增强、添加日志等操作。与 JDK 动态代理不同的是CGLIB 动态代理可以代理类而不仅限于接口。