• Spring总结七:AOP动态代理的实现


    Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类。

    首先我们来用代码简单演示jdk动态代理:

    现在有一个商品的增删改查的操作

    /**
     * 商品操作接口
     */
    public interface ProductService {
        public void add();
        public void edit();
        public void delte();
        public void select();
    }
    
    /**
     * 实现类
     */
    public class ProductServiceImpl implements ProductService {
        @Override
        public void add() {
            System.out.println("添加商品");
        }
    
        @Override
        public void edit() {
            System.out.println("修改商品");
        }
    
        @Override
        public void delte() {
            System.out.println("删除商品");
        }
    
        @Override
        public void select() {
            System.out.println("查询商品");
        }
    }

    我们编写一个基于jdk的动态代理(实现InvocationHandler接口):

    public class JdkProxy implements InvocationHandler {
    
        //被代理的目标
        private Object target;
    
        //构造函数 传入目标对象
        public JdkProxy(Object target) {
            this.target = target;
        }
    
        //提供创建代理对象的方法
        public Object createProxy() {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        /**
         * 实现InvocationHandler接口的回调方法, 拦截目标对象所有方法都会执行invoke方法
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("我是代理,我对被代理的目标有绝对的控制权...");
            Object returnVal = method.invoke(target, args);
            System.out.println("--------------------------------------");
            return returnVal;
        }
    }

    测试代码:

    public class JdkProxyTest {
        @Test
        public void testJdkProxy() {
            //创建对象
            ProductService target = new ProductServiceImpl();
            //创建代理对象
            JdkProxy jdkProxy = new JdkProxy(target);
            //代理面向接口
            ProductService proxy = (ProductService) jdkProxy.createProxy();
            //通过代理调用方法
            proxy.add();
            proxy.edit();
            proxy.delte();
            proxy.select();
        }
    }

    运行结果:

    jdk的代理,目标必须有接口

    而cglib的代理不管有没有接口都可以

    下面简单说一下cglib的动态代理:

    ProductService

    public class ProductService {
        public void add() {
            System.out.println("添加商品");
        }
    
        public void edit() {
            System.out.println("修改商品");
        }
    
        public void delte() {
            System.out.println("删除商品");
        }
    
        public void select() {
            System.out.println("查询商品");
        }
    }

    CglibProxy:

    public class CglibProxy {
        private Object target;
    
        public CglibProxy(Object target) {
            this.target = target;
        }
    
        public Object createProxy() {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    // 增强的功能
                    System.out.println("这么巧,我也是代理.......................");
                    // 原来的功能
                    Object returnVal = method.invoke(target, args);
                    return returnVal;
                }
            });
            // 返回 代理对象(增强之后的对象)
            return enhancer.create();
        }
    
    }

    测试代码:

    public class CglibProxyTest {
        @Test
        public void testCglibProxy() {
            ProductService target = new ProductService();
            CglibProxy cglibProxy = new CglibProxy(target);
            ProductService proxy = (ProductService) cglibProxy.createProxy();
            proxy.add();
            proxy.edit();
            proxy.delte();
            proxy.select();
        }
    }

    运行结果:

    其实除了动态代理,还有静态代理,以后总结设计模式的时候再详细说。设计模式之 代理模式

  • 相关阅读:
    使用Scanner接受用户键盘输入的值
    使用 c3p0 连接数据库
    JDBC连接数据库
    SQL高级查询
    sql中的内连接和外连接
    存储过程的优缺点
    DML命令和DQL命令
    --sql语句创建表的同时添加外键约束
    JavaScript操作DOM对象(赠删表格中的元素)
    特效时钟
  • 原文地址:https://www.cnblogs.com/blazeZzz/p/9311045.html
Copyright © 2020-2023  润新知