java-动态代理
一、Java自带的动态代理
1、概述:
JDK动态代理主要涉及java.lang.reflect包下的Proxy类和InvocationHandler接口。 JDK代理实现的三个要点:
通过java.lang.reflect.Proxy类来动态生成代理类
代理类要实现InvocationHandler接口
JDK代理只能基于接口进行动态代理
2、代码结构
3、Jdk_ProxyService
package com.turtle.jdk; public interface Jdk_ProxyService { public void doUpdate(); public void doSave(String name); public String doFind(); }
4、Jdk_ProxyServiceImpl
package com.turtle.jdk; /** * JDk的动态代理一定要满足实现接口的步骤 */ public class Jdk_ProxyServiceImpl implements Jdk_ProxyService { @Override public void doUpdate() { System.out.println("进行更新操作"); } @Override public void doSave(String name) { System.out.println("进行保存操作==="+name); } @Override public String doFind() { System.out.println("进行查询操作"); return "SUCCESS"; } }
5、Jdk_MyInvocationHandler
package com.turtle.jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; // 代理类 public class Jdk_MyInvocationHandler implements InvocationHandler { // 这个就是我们要代理的真实对象 private Object target; // 构造方法,给我们要代理的真实对象赋初值 public Jdk_MyInvocationHandler(Object target) { this.target = target; } /* *invoke方法方法参数解析 *Object proxy:指被代理的对象。 *Method method:要调用的方法 *Object[] args:方法调用时所需要的参数 *InvocationHandler接口的子类可以看成代理的最终操作类。 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始进行代理的增强"); Object result= null; try{ // 利用反射动态的来反射方法,这就是动态代理和静态代理的区别 result = method.invoke(target,args); }catch (Exception e){ e.printStackTrace(); }finally { System.out.println("代理的增强完毕了"); } return result; } }
6、TestJdk
package com.turtle.jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class TestJdk { public static void main(String[] args) { // 我们要代理的真实对象 Jdk_ProxyService jdkProxyService = new Jdk_ProxyServiceImpl(); // 我们要代理哪个真实对象,就将该对象传进去 InvocationHandler invocationHandler = new Jdk_MyInvocationHandler(jdkProxyService); /* *newProxyInstance方法参数解析 *ClassLoader loader:类加载器 *Class<?>[] interfaces:得到全部的接口 *InvocationHandler h:得到InvocationHandler接口的子类实例 */ Jdk_ProxyService jdkProxyServiceProxy = (Jdk_ProxyService)Proxy.newProxyInstance(jdkProxyService.getClass().getClassLoader(),jdkProxyService.getClass().getInterfaces(),invocationHandler); //jdkProxyServiceProxy.doFind(); // jdkProxyServiceProxy.doSave("测试"); jdkProxyServiceProxy.doUpdate(); } }
二、使用CgliB来完成动态代理
1、概述:
使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
2、代码结构、Jar包:
3、Cglib_ProxyService,被代理对象
package com.turtle.cglib; public class Cglib_ProxyService { /** * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的 */ public final void doDel(){ System.out.println("正在进行删除操作"); } /** * 有返回值、无参数 * @return */ public String doFind(){ System.out.println("正在进行查询操作"); return "SUCCESS"; } /** * 有参数、有返回值 * @param name * @return */ public String doSave(String name){ System.out.println("正在进行保存操作"+name); return "SUCCESS"; } /** * 无参数、无返回值 */ public void doUpdate(){ System.out.println("正在进行修改操作"); } }
4、Cglib_MyMethodInterceptor,我们自定义的代理,对对象做增强操作
package com.turtle.cglib; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 自己建立的AOP注入 */ public class Cglib_MyMethodInterceptor implements MethodInterceptor { /** * @param o cglib生成的代理对象 * @param method 被代理对象方法 * @param objects 方法入参 * @param methodProxy 代理方法 * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { String result = null; // 通过方法签名来确定我们需要对哪些方法做增强操作 if(methodProxy.getSignature().getName() == "doUpdate"){ System.out.println("对doUpdate方法做前置增强"); methodProxy.invokeSuper(o,objects); System.out.println("对doUpdate方法做后置增强"); } if(methodProxy.getSignature().getName() == "doSave"){ System.out.println("对doSave方法做前置增强"); methodProxy.invokeSuper(o,objects); System.out.println("对doSave方法做后置增强"); } if(methodProxy.getSignature().getName() == "doDel"){ System.out.println("对doDel方法做前置增强"); methodProxy.invokeSuper(o,objects); System.out.println("对doDel方法做后置增强"); } if(methodProxy.getSignature().getName() == "doFind"){ System.out.println("对doFind方法做前置增强"); result = methodProxy.invokeSuper(o,objects).toString(); System.out.println("对doFind方法做后置增强"); } return result; } }
5、Cglib_ProxyFactory,创建一个工厂来实例化我们的代理。
package com.turtle.cglib; import net.sf.cglib.proxy.Enhancer; /** * 将用来创建代理对象的操作放到简单工厂里面来实现 */ public class Cglib_ProxyFactory<T> { public T createProxyObj(T obj){ // 通过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(obj.getClass()); // 设置enhancer的回调对象 enhancer.setCallback(new Cglib_MyMethodInterceptor()); // 创建代理对象 return (T)enhancer.create(); } }
6、TestCglib,测试结果。
package com.turtle.cglib; public class TestCglib { public static void main(String[] args) { // 取得工厂对象 Cglib_ProxyFactory<Cglib_ProxyService> cglibProxyFactory = new Cglib_ProxyFactory<>(); // 利用工厂来创建代理对象 Cglib_ProxyService cglibProxyService = cglibProxyFactory.createProxyObj(new Cglib_ProxyService()); // 通过代理对象调用目标方法 // 无参数、无返回值的方法 // cglibProxyService.doUpdate(); // 有参数的方法 // cglibProxyService.doSave("保存"); // 有返回值的方法 // String result = cglibProxyService.doFind(); // System.out.println(result); // 被final修饰的方法 cglibProxyService.doDel(); } }
三、总结