动态代理(cglib实现)
cglib是利用生成子类继承父类的方法实现的动态代理
原理实例
首先构造父类Singer
public class Singer { public void dance(){ System.out.println("跳舞"); } public void singing(){ System.out.println("唱歌"); } }
构造子类继承父类,实现代理
public class SingerSub extends Singer { @Override public void dance() { System.out.println("经纪人商量合同"); super.dance(); System.out.println("收钱"); } @Override public void singing() { System.out.println("经纪人商量合同"); super.singing(); System.out.println("收钱"); } }
方法执行
public class Main { public static void main(String[] args) { Singer singer = new SingerSub(); singer.singing(); singer.dance(); } }
运行结果
可以看出,我并未用静态代理,也没有用proxy类去实现,就是单纯的继承关系。理解到这就是cglib的原理
cglib代码实例
首先之前一样建立Singer接口
public interface Singer { void sing(); void dance(); }
然后实现方法
public class ZStar implements Singer{ @Override public void sing() { System.out.println("我会唱歌......."); } @Override public void dance() { System.out.println("我会跳舞......"); } }
建立代理规则,这一步和Proxy有很大相似性,只不过是proxy继承的InvocationHandler接口,而cglib继承的是MethodInterceptor,
public class TargetCglib implements MethodInterceptor { private ZStar zStar; public TargetCglib(ZStar zStar) { this.zStar = zStar; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("签合同"); Object invoke = methodProxy.invokeSuper(o, objects);//调用原方法 //Object invoke = method.invoke(zStar, objects); //Object invoke = methodProxy.invokeSuper(zStar, objects); System.out.println("收钱"); return invoke; } }
其中注释的内容是三种不同的代理执行方法的方法,可以自己试试。
要说明的是 invokeSuper调用的是被代理类的方法, 但只有代理类才存在基类, 必须使用代理类作为obj参数调用 invoke调用的是增强方法, 必须使用被代理类的对象调用, 使用代理类会造成OOM
主方法运行
public class Main { public static void main(String[] args) { Enhancer en = new Enhancer();//用来帮我们生成代理对象 en.setSuperclass(ZStar.class);//设置要代理的目标类 en.setCallback(new TargetCglib(new ZStar()));//设置执行规则,相当于proxy的Ruler ZStar s = (ZStar)en.create();//创造代理对象 s.dance();//方法测试 System.out.println("********************"); s.sing(); } }
其中Enhancer就是cglib用来帮我们生成代理对象的,再用setSuperclass设定代理的目标类,在设定代理规则,也就是我们上边设定的签合同收钱,create()生成代理对象,测试运行得到结果
注意:测试要是发生报异常
Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type
.................
Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type
可以试着换一下cglib的jar包,更换成