zoukankan      html  css  js  c++  java
  • JDK动态代理与CGLib动态代理

    JDK动态代理:

    a、先定义一个接口,这个接口中的方法是“目标方法”

    package com.brickworkers;
    
    public interface Sky {
    
        public void rain();
    
    }

    b、接着写一个这个接口的具体实现:

    package com.brickworkers;
    
    public class SkyImpl implements Sky{
    
        @Override
        public void rain() {
            System.out.println("it`s raining");
        }
    
    
    }

    c、如果要完成动态代理,首先需要定义一个InvocationHandler接口的子类:

    package com.brickworkers;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class MyInvocationHandler implements InvocationHandler {
    
        //目标对象
        private Object obj = null;
    
    
        //获取目标对象的代理对象
        public Object getProxy(Object obj){
            this.obj = obj;
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        }
    
        //控制执行目标对象的方法
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("目标对象方法执行之前");
            Object result = method.invoke(obj, args);
            System.out.println("目标对象方法执行之后");
            return result;
        }
    
    }

    d:JDK动态代理测试类:

    package com.brickworkers;
    
    public class ProxyTest {
    
        public static void main(String[] args) {
            //实例化InvocationHandler
            MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
            //生产代理对象
            Sky sky = (Sky) myInvocationHandler.getProxy(new SkyImpl());
            sky.rain();
        }
    
    }
    
    //执行结果:  目标对象方法执行之前
    //            it`s raining
    //          目标对象方法执行之后

    为什么JDK动态代理只能局限于接口呢?查阅了一些技术文档和JDK动态代理的源码,发现在反编译产生的proxyTest.class中,类的定义如下:

    import dynamic.proxy.UserService;  
    import java.lang.reflect.*;  
    
    public final class $ProxyTest extends Proxy  
        implements Sky
    { 
        ......
    }

    从反编译的源码可以看出,proxyTest继承了Proxy,然而在Java中只支持单继承,但是可以实现多个接口,所以JDK动态代理只能局限于接口。

    那么JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,要实现动态代理要怎么办呢?这个时候就需要CGLib动态代理了。

    CGLib动态代理:

    CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有分类方法的调用,顺势织入和横切逻辑。-http://blog.csdn.net/yakoo5/article/details/9099133/

    点击下载编写CGlib动态代理测试所需jar包

    a、定义一个目标对象:

    package com.brickworkers;
    
    public class Color {
    
        public void showColor(){
            System.out.println("red");
        }
    
    }

    b、如果要完成动态代理,首先需要定义一个MethodInterceptor接口的子类:

    package com.brickworkers;
    
    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 MyCglib implements MethodInterceptor {
    
        //目标对象
        private Object obj = null;
    
        public Object getProxy(Object obj){
            this.obj = obj;
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(obj.getClass());
            // 回调方法  
            enhancer.setCallback(this);  
            // 创建代理对象  
            return enhancer.create();
    
        }
    
        @Override
        public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("目标对象方法执行之前");
            Object result = methodProxy.invoke(obj, args);
            System.out.println("目标方法执行之后");
            return result;
        }
    
    }

    c、CGLib动态代理测试类:

    package com.brickworkers;
    
    public class CGLibTest {
    
        public static void main(String[] args) {
            MyCglib myCglib = new MyCglib();
            Color color = (Color) myCglib.getProxy(new Color());
            color.showColor();
        }
    }
    //执行结果:目标对象方法执行之前
    //              red
    //          目标方法执行之后

    因为CGLib动态代理是创建一个子类来实现的,那么对于继承的定义,final类是无法进行代理的。

  • 相关阅读:
    MySQL行(记录)的详细操作一 介绍 二 插入数据INSERT 三 更新数据UPDATE 四 删除数据DELETE 五 查询数据SELECT 六 权限管理
    {MySQL完整性约束}一 介绍 二 not null与default 三 unique 四 primary key 五 auto_increment 六 foreign key 七 作业
    { MySQL基础数据类型}一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型
    MySQL的sql_mode模式说明及设置
    {MySQL存储引擎介绍}一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用
    {MySQL的库、表的详细操作}一 库操作 二 表操作 三 行操作
    小爬爬2.数据解析
    小爬爬2:fiddler安装和了解fiddler
    小爬爬2.回顾
    小爬爬1.requests基础操作
  • 原文地址:https://www.cnblogs.com/wyb628/p/8511174.html
Copyright © 2011-2022 走看看