Java动态代理初识——动态代理JDK和CGLIB

一、代理模式类型:

代理:客户对象不能直接与目标对象进行调用操作,代理对象为客户对象提供对目标对象调用真实对象方法,避免对真实对象访问直接访问的复杂性,可对原有业务功能进行增强(方法执行前后可进行其他操作),无需修改其原有内部代码

1、静态代理:直接类似于一个代理对象只能为一个真实对象代理,代理类所实现的方法在运行之前就已经确定,扩展性、可维护性差
2、动态代理:与静态代理不同的是,程序运行时代理对象才被创建出来,代理一个接口下的多个实现类,在运行时才确定为哪个真实对象生成代理对象。为哪个对象生成代理对象是动态的

二、简单实例动态代理
1、JDK动态代理简单样例

创建UserService接口以及其实现类UserServiceImpl

//真实对象抽象类
public interface UserService {
    String call(String param);
}
//真实对象实现类
@Service
public class UserServiceImpl implements UserService{
    @Override
    public String call(String param) {
        System.out.println("您好!"+param+"先生");
        return "end";
    }
}
//为真实对象UserService代理类ObjectHandler
public class ObjectHandler implements InvocationHandler {

    private Object object;

    /**
     * 实例化代理对象
     * @param object 真实对象
     * @return 代理对象
     */
    public Object newProxy(Object object){
        //拿到对真实对象的引用
        this.object = object;
        //Proxy.newProxyInstance参数:真实对象的类加载器,需要代理的接口以及继承InvocationHandler代理类本身
        //Proxy.newProxyInstance会返回实现这些接口的代理类对象
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    //增强器
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();//方法执行前增强
        Object result = method.invoke(object,args);
        after();//方法执行后增强
        return result;//返回真实对象返回参数
    }

    private static void before(){
        System.out.println("拨打中,。。");
    }
    private static void after(){
        System.out.println("挂断,。。");
    }
}
     @org.junit.Test
    public void JdKTest(){
        //实例化一个UserService对象
        //newProxyInstance方法需要实现接口的对象,如果提供的是接口对象,就会报映射异常【java.lang.ClassCastException: com.sun.proxy.$Proxy4 cannot be cast to com.test.kafka.demo1.invokeTest.UserService】
        //由此看出jdk代理只能对实现接口UserServiceImpl类生成代理
        UserService userService = new UserServiceImpl();
        ObjectHandler objectHandler = new ObjectHandler();
        //通过Proxy类提供的一个newProxyInstance方法用来创建返回一个接口对应实现类(代理类)对象
        UserService userService1 = (UserService)objectHandler.newProxy(userService);
        System.out.println(userService1.call("王"));
    }

Java动态代理初识——动态代理JDK和CGLIB_第1张图片

2、CGlib动态代理

CGlib(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。CGlib会在运行期间,生产为真实对象代理的代理类,与JDK动态代理所不同的是,CGlib可为没有实现接口的对象进行代理,而JDK只能代理实现接口的对象。

/**
* 跟JDK中InvocationHandler类似,cglib实现动态代理,需要实现MethodInterceptor接口
**/
public class ObjectInterceptor implements MethodInterceptor {

    public Object newProxyObject(Object object){
        //Enhance为cglib库里关键类(代理类),用来生成代理的工厂类,可生成继承真实对象的子类
        Enhancer enhancer = new Enhancer();
        //设置为哪个类进行代理
        enhancer.setSuperclass(object.getClass());
        //添加回调函数,给enhance设置增强器ObjectInterceptor
        enhancer.setCallback(this);
        //由enhance生产的代理类对象
        return enhancer.create(); //com.test.kafka.demo1.invokeTest.UserServiceImpl$$EnhancerByCGLIB$$6ca916ca@4de5031f
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object result = methodProxy.invokeSuper(o,objects);//入参:真实对象的引用、被代理接口方法、方法所需入参、代理类方法
        after();
        return result;
    }

    private static void before(){
        System.out.println("拨打中,。。");
    }
    private static void after(){
        System.out.println("挂断,。。");
    }
}
 @org.junit.Test
    public void CglibTest(){
    	//可在code下生成cglib运行时所生成的class类,其中一个是我们需要的代理类,另外两个是索引类
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code");
        //实例化一个UserService对象
        UserService userService = new UserServiceImpl();
        ObjectInterceptor objectInterceptor = new ObjectInterceptor();
        //通过Proxy类提供的一个newProxyInstance方法用来创建返回一个接口对应实现类(代理类)对象
        //生产代理类对象com.test.kafka.demo1.invokeTest.UserServiceImpl$$EnhancerByCGLIB$$6ca916ca@52aa2946
        UserService userService1 = (UserService)objectInterceptor.newProxyObject(userService);
        System.out.println(userService1.call("王"));
    }

运行结果如下:
Java动态代理初识——动态代理JDK和CGLIB_第2张图片

你可能感兴趣的:(Java,Spring,java,代理模式)