JAVA动态代理和方法拦截(使用CGLib实现AOP、方法拦截、委托)
AOP用CGLib更简便、更可控。
动态代理的实现非常优雅。
实体类:
public class SampleClass { public String MyFunction1(String input) { System.out.println("MyFunction1方法被调用:Hello:" + input); return "Hello:" + input; } public String MyFunction2(String input) { System.out.println("MyFunction2方法被调用:Hello:" + input); return "Hello:" + input; } }
import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Dispatcher; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.FixedValue; import net.sf.cglib.proxy.LazyLoader; import net.sf.cglib.proxy.NoOp; import net.sf.cglib.proxy.ProxyRefDispatcher; public class CgLibTest { private static String MyName = ""; public static void main(String[] args) { MyName = "王昕"; DoAOP(); Enhancer enhancer1 = EnhancerNoOp(); SampleClass proxy = (SampleClass) enhancer1.create(); String strOutput = proxy.MyFunction2("赵七"); System.out.println("EnhancerNoOp:"+strOutput); Enhancer enhancer2 = EnhancerFixedValue(); SampleClass proxy2 = (SampleClass) enhancer2.create(); String strOutput2 = proxy2.MyFunction2("赵七"); System.out.println("EnhancerFixedValue:"+strOutput2); } private static void DoAOP() { MyInterceptor cglib = new MyInterceptor(); SampleClass bookCglib = (SampleClass) cglib .getInstance(new SampleClass()); bookCglib.MyFunction2("张三"); } // 该回调将替代原类的方法实现 private static Enhancer EnhancerFixedValue() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleClass.class); enhancer.setCallback(new FixedValue() { @Override public Object loadObject() throws Exception { //返回 MyName 作为输入参数的; return new SampleClass().MyFunction2(MyName); } }); return enhancer; } //执行原(Super)类方法 private static Enhancer EnhancerNoOp() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleClass.class); enhancer.setCallback(NoOp.INSTANCE); return enhancer; } //延迟加载 private static Enhancer EnhancerLazyLoader() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleClass.class); enhancer.setCallback(new LazyLoader() { @Override public Object loadObject() throws Exception { //return "回调后的返回值"; return new SampleClass().MyFunction2(MyName); } }); return enhancer; } private static Enhancer EnhancerProxyRefDispatcher(final String obj1) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleClass.class); enhancer.setCallback(new ProxyRefDispatcher() { @Override public Object loadObject(Object obj2) throws Exception { return new SampleClass().MyFunction2(obj1 + (String)obj2); } }); return enhancer; } }
AOP拦截模拟类:
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class MyInterceptor implements MethodInterceptor { private Object target; public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override // 回调方法 public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("拦截前,做些事情"); proxy.invokeSuper(obj, args); System.out.println("拦截后,再做些事情"); return null; } }
输出:
拦截前,做些事情
MyFunction2方法被调用:Hello:张三
拦截后,再做些事情
MyFunction2方法被调用:Hello:赵七
EnhancerNoOp:Hello:赵七
MyFunction2方法被调用:Hello:王昕
EnhancerFixedValue:Hello:王昕
MethodDelegate
方法委托: 实现类似C#的委托。将方法调用绑定到某个接口的特定方法
public void testMethodDelegate() throws Exception { SampleBean bean = new SampleBean(); bean.setValue("Hello cglib!"); BeanDelegate delegate = (BeanDelegate) MethodDelegate.create(bean, "getValue", BeanDelegate.class); assertEquals("Hello world!", delegate.getValueFromDelegate2()); } public interface BeanDelegate { //String getValueFromDelegate1(); String getValueFromDelegate2(); }
BulkBean
使用数组访问bean的访问器方法调用
public void testBulkBean() throws Exception { BulkBean bulkBean = BulkBean.create(SampleBean.class, new String[] { "getValue" }, new String[] { "setValue" }, new Class[] { String.class }); SampleBean bean = new SampleBean(); bean.setValue("Hello world!"); assertEquals(1, bulkBean.getPropertyValues(bean).length); assertEquals("Hello world!", bulkBean.getPropertyValues(bean)[0]); bulkBean.setPropertyValues(bean, new Object[] { "Hello cglib!" }); assertEquals("Hello cglib!", bean.getValue()); }
public class SampleBean { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
关于作者:
王昕(QQ:475660)
在广州工作生活30余年。十多年开发经验,在Java、即时通讯、NoSQL、BPM、大数据等领域较有经验。
目前维护的开源产品:https://gitee.com/475660
目前维护的开源产品:https://gitee.com/475660