JDK动态代理:是Java标准库提供的一种动态代理实现方式,基于接口生成代理对象。使用Proxy
类和InvocationHandler
接口来创建代理对象,被代理的类必须实现接口。
CGlib动态代理:使用CGLib库实现,通过生成目标类的子类来创建代理对象。不需要目标类实现接口,可以直接代理普通类。
区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。
注意:类的私有方法、类的pulibc+final方法、以及final类,JDK和CGLib均无法进行动态代理,因为私有、final均不可被代理。
1. 接口类
public interface DDService { public void addUser(String id,String password); }
2. 实现类
public class DDServiceImpl implements DDService{ @Override public void addUser(String id, String password) { System.out.println("调用 addUser方法"); } }
3. JDK动态代理类
public class JDKProxy implements InvocationHandler { //需要代理的目标对象 private Object targetObject; /** * 创建 JDK 动态代理类实例 */ public Object newProxy(Object targetObject) { // 将目标对象传入进行代理 this.targetObject = targetObject; // JDK提供的用于创建代理对象的静态方法, 返回代理对象 return Proxy.newProxyInstance( targetObject.getClass().getClassLoader(), // 指定目标类的类加载 targetObject.getClass().getInterfaces(), // 代理需要实现的接口 this // 调用代理对象逻辑的拦截器,即InvocationHandler 实现类 ); } /** * 动态代理方法拦截器。每当代理对象的方法被调用时,都会进入该方法 * * @param proxy 代理目标对象的代理对象,它是真实的代理对象。 * @param method 被拦截的目标类的方法 * @param args 执行目标类的方法的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //进行逻辑处理的函数 checkPopedom(); //调用目标对象上对应的方法,并传入相应的参数。 Object ret = method.invoke(targetObject, args); //返回目标方法的执行结果。 return ret; } /** * 检查权限 */ private void checkPopedom() { System.out.println("检查权限"); } }
4. CGLib动态代理类
public class CGLibProxy implements MethodInterceptor { /** * 创建 CGLib 动态代理类实例 */ public Object createProxyObject(Object targetObject) { // 创建Enhancer对象,用于创建代理对象 Enhancer enhancer = new Enhancer(); // 设置目标类的类加载器 enhancer.setClassLoader(targetObject.getClass().getClassLoader()); // 设置代理目标类 enhancer.setSuperclass(targetObject.getClass()); // 设置方法拦截器 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } /** * 动态代理方法拦截器。每当代理对象的方法被调用时,都会进入该方法 * * @param proxy 代理目标对象的代理对象,它是真实的代理对象。 * @param method 被拦截的目标类的方法 * @param args 执行目标类的方法的参数 * @param methodProxy CGLib提供的用于调用目标方法的代理对象。通过这个MethodProxy对象,可以调用目标方法而不必使用Java的反射机制。 */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //进行逻辑处理的函数 if ("addUser".equals(method.getName())) { //检查权限 checkPopedom(); } //调用目标对象上对应的方法,并传入相应的参数。 Object obj = methodProxy.invokeSuper(proxy, args); return obj; } private void checkPopedom() { System.out.println("检查权限:checkPopedom()!"); } }
5. Test类
public static void main(String[] args) { System.out.println("JDKProxy:======================"); DDService userManagerJDK = (DDService) new JDKProxy().newProxy(new DDServiceImpl()); userManagerJDK.addUser("tom", "root"); System.out.println("CGLib:======================"); DDService userManager = (DDService) new CGLibProxy().createProxyObject(new DDServiceImpl()); userManager.addUser("tom", "root"); }
输出
JDKProxy:====================== 检查权限 调用 addUser方法 CGLib:====================== 检查权限:checkPopedom()! 调用 addUser方法
标签:对象,Object,代理,几种,动态,方法,public,targetObject From: https://www.cnblogs.com/yifanSJ/p/17580439.html