在有的时候,我们在调用类的方法时,需要在类的方法前面和后面做一些事,比如说在每个方法前面打log,这时我们可以使用动态代理。动态代理分为JDK动态代理和CGLib动态代理。
1. JDK动态代理
被代理类实现的接口
package com.lk.proxy.service; public interface PlanService { void addPlan(String plan); void deletePlan(int id); }
被代理类
package com.lk.proxy.service.impl; import com.lk.proxy.service.PlanService; public class PlanServiceImpl implements PlanService { @Override public void addPlan(String plan) { System.out.println("execute add plan method, plan = " + plan); } @Override public void deletePlan(int id) { System.out.println("execute delete plan method"); } }
package com.lk.proxy.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class CustomProxyHandler implements InvocationHandler { private Object target; public CustomProxyHandler(Object target) { super(); this.target = target; } public CustomProxyHandler() { super(); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("do some thing before invoke"); Object result = method.invoke(target, args); System.out.println("do some thing after invoke"); return result; } public void setTarget(Object target) { this.target = target; } }
测试
package com.lk.proxy.test; import java.lang.reflect.Proxy; import com.lk.proxy.proxy.CustomProxyHandler; import com.lk.proxy.service.PlanService; import com.lk.proxy.service.impl.PlanServiceImpl; public class TestProxy { public static void main(String[] args) { PlanService planServiceProxy = new PlanServiceImpl(); CustomProxyHandler proxyHandler = new CustomProxyHandler(planServiceProxy); PlanService planService = (PlanService) Proxy.newProxyInstance(planServiceProxy.getClass().getClassLoader(), planServiceProxy.getClass().getInterfaces(), proxyHandler); planService.addPlan("plan 1"); } }
2. CGLib动态代理
被代理类
package com.lk.proxydemo; public class UserService { public void sayHello() { System.out.println("Say Hello"); } }
代理处理类
package com.lk.proxydemo; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class<?> superClass) { //设置需要创建子类的类 enhancer.setSuperclass(superClass); enhancer.setCallback(this); //通过字节码技术动态创建子类实例 return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("do some thing before " + method.getName()); //通过代理类调用父类 Object result = proxy.invokeSuper(obj, args); System.out.println("do some thing after " + method.getName()); return result; } }
测试类
package com.lk.proxydemo; public class ProxyTest { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); UserService userService = (UserService) proxy.getProxy(UserService.class); userService.sayHello(); } }
3. 总结
JDK动态代理中被代理类必须要实现相应接口,而CGLib不需要,CGLib是通过字节码技术为被代理类创建一个子类。
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。
浙公网安备 33010602011771号