浅谈Java代理二:Cglib动态代理-MethodInterceptor

 

CGLib动态代理特点

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

 

 

示例业务逻辑:

1-有一个明星叫胡歌(class HuGe)

3-找明星做事情需要经过助理(ProxyFactory )

4-如果要找胡歌唱歌、演戏,需要先找助理,然后助理去找胡歌唱歌、演戏(class testProcyFactory)

 

 

 

1-被代理类(没有实现任何接口)

package com.huishe.testOfSpring.methodinterceptor;

public class HuGe {

    public void sing(String song) {
        System.out.println("胡歌演唱: " + song);
    }

    public String act(String teleplay) {
        System.out.println("胡歌决定出演电视剧: " + teleplay);
        return "胡歌答应出演电视剧: " + teleplay;
    }
}

2-代理工厂(即创建代理的通用写法)

package com.huishe.testOfSpring.methodinterceptor;

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 ProxyFactory implements MethodInterceptor{
    //要代理的原始对象
    private Object object;
    
    //1-创建代理对象
    public Object createProcy(Object target){
        this.object = target;
        //1-Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展
        Enhancer enhancer=new Enhancer();  
        //2-将被代理类HuGe设置成父类
        enhancer.setSuperclass(this.object.getClass());  
        //3-设置拦截器
        enhancer.setCallback(this);  
        //4-动态生成一个代理类
        Object objProxy = enhancer.create();  
        
        return objProxy;
        
    }
    
    //2-实现MethodInterceptor的intercept方法
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before: " + method);
        //调用proxy.invoke()方法,会报java.lang.StackOverflowError错误,原因是invoke()内部会一直被反复调用
        //Object object = proxy.invoke(obj, args);
        Object object = proxy.invokeSuper(obj, args);
        System.out.println("after: " + method);
        return object;
    }
}

 3-进行测试

package com.huishe.testOfSpring.methodinterceptor;

import org.junit.Test;

import net.sf.cglib.proxy.Enhancer;

public class cglibMethodInterceptorTest {

    @Test
    public void testProcyFactory(){
        //1-实例化需要被代理的类
        HuGe huGe = new HuGe();
        //2-实例化代理工厂
        ProxyFactory cglibProxy = new ProxyFactory();
        //3-动态生成一个代理类,并从Object强制转型成父类型HuGe
        HuGe hg =(HuGe)cglibProxy.createProcy(huGe);
        
        //4-执行动态代理类的方法
        hg.sing("逍遥叹");
        hg.act("琅琊榜");
        
    }
    
}

 4-测试结果

日志输出:

before: public void com.huishe.testOfSpring.methodinterceptor.HuGe.sing(java.lang.String)
胡歌演唱: 逍遥叹
after: public void com.huishe.testOfSpring.methodinterceptor.HuGe.sing(java.lang.String)
before: public java.lang.String com.huishe.testOfSpring.methodinterceptor.HuGe.act(java.lang.String)
胡歌决定出演电视剧: 琅琊榜
after: public java.lang.String com.huishe.testOfSpring.methodinterceptor.HuGe.act(java.lang.String)

 

 

参考资料

1-https://blog.csdn.net/jiaotuwoaini/article/details/51675684
2-https://www.cnblogs.com/writeLessDoMore/p/6973853.html

posted on 2018-11-21 19:09  我不吃番茄  阅读(4476)  评论(0编辑  收藏  举报