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的基本原理就是对类进行增强,在代理类中抽象出公共方法。

posted @ 2020-06-05 12:02  独钓寒江到酒家  阅读(1016)  评论(0编辑  收藏  举报