zoukankan      html  css  js  c++  java
  • Spring中的Aop(一)--使用Proxy.newProxyInstance和cglib创建代理对象

    一、什么是Aop

    Aop是面向切面编程的简称,是通过预编译和运行期间动态代理实现程序功能的一共技术方式。
    下面我们举一个实际的例子来进行说明。
    例子:手机生产厂家只生产手机,手机代理帮助厂家卖手机,并收取20%的费用,示例图如下:

    下面我们编写一个类表示厂家,一个代理类表示代理商,来实现该功能。

    二、使用Proxy.newProxyInstance方法对实现接口的类进行动态代理

    使用Proxy创建代理类,被代理的类必须要实现接口,下面我们开始编写代码实现这个过程;

    2.1 定义生产厂商

    定义接口

    package org.study.proxy;
    public interface IProducer {
        /**
         * 销售产品,并拿到钱
         * @param amount
         */
        void saleProduct(float amount);
    
        /**
         * 提供售后服务
         * @param amount
         */
        void afterService(float amount);
    }
    

    实现接口

    package org.study.proxy.impl;
    import org.study.proxy.IProducer;
    public class ProducerImpl implements IProducer {
        @Override
        public void saleProduct(float amount) {
            System.out.println("saleProduct money:" + amount);
        }
        @Override
        public void afterService(float amount) {
            System.out.println("afterService money:" + amount);
        }
    }
    
    

    我们的生产厂家类已经编写完成;

    2.2 编写代理商,代理商对saleProduct方法进行增强

    package org.study.proxy;
    import org.study.proxy.impl.ProducerImpl;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    public  class Client {
        public static void main(String[] args) {
            IProducer producer =new ProducerImpl();
            /**
             * ClassLoader loader 类加载器,用于加载代理对象的字节码
             * Class<?>[] interfaces 字节码数组,用于让代理对象和被代理对象有相同的方法
             * InvocationHandler h 处理方法,用于方法增强
             */
            IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(
                    producer.getClass().getClassLoader(),
                    producer.getClass().getInterfaces(),
                    /**
                     * Object proxy 被代理的类
                     * Method method 被代理类的方法
                     * Object[] args 方法参数
                     */
                    new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                            if (method.getName().equals("saleProduct")) {
                                float amount = (float) args[0];
                                return method.invoke(producer, amount * (float) 0.8);
                            } else {
                                return method.invoke(producer, args);
                            }
                        }
                    });
            proxyProducer.saleProduct(1000f);
            proxyProducer.afterService(1000f);
        }
    }
    

    主要的技术点:
    使用Proxy.newProxyInstance方法,对类进行增强,并返回了和代理类同样的对象和方法;

    2.3 运行结果


    通过运行结果,可以看到,代理类帮我们卖出去了产品,厂商拿到了80%的钱,目标实现;

    三、使用cglib对不实现接口的类进行动态代理

    1、代码编写

    cglib是一个类库,它可以在运行期扩展Java类与实现Java接口;cglib中使用Enhancer类来进行代理,代码如下:

    package org.study.cglib;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    public class Client {
        public static void main(String[] args) {
            Producer producer = new Producer();
            Producer enhancerProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
                /**
                 * @param proxy 被代理对象
                 * @param method 代理的方法
                 * @param args 方法参数
                 * @param methodProxy 当前执行方法的代理对象
                 * @return
                 * @throws Throwable
                 */
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    if (method.getName().equals("saleProduct")) {
                        float amount = (float) args[0];
                        return method.invoke(producer, amount * (float) 0.8);
                    } else {
                        return method.invoke(producer, args);
                    }
                }
            });
            enhancerProducer.saleProduct(1000f);
            enhancerProducer.afterService(1000f);
        }
    }
    

    2、运行结果


    方法依然如预期执行了。

    四、总结

    1、使用cglib类库,来对类进行代理和Proxy的用法基本相同,都返回一个增强后的类,该类和原来的类,拥有相同的方法,并增加了某些方法的功能;
    2、Aop的基本原理就是对类进行增强,在代理类中抽象出公共方法。

  • 相关阅读:
    mysql查看锁表情况
    利用xtrabackup备份mysql数据库
    /proc/sys/vm/参数
    linux的sysctl基本配置
    python计算apache总内存
    ip_conntrack table full dropping packet错误的解决方法
    apachetop 实时监控apache指定日志
    mysql大表myisam的导入
    编译安装php5.5和php-fpm
    tshark 抓包分析
  • 原文地址:https://www.cnblogs.com/zqllove/p/13048938.html
Copyright © 2011-2022 走看看