动态代理基于接口与子类的实现

1 AOP 的作用及优势

		作用:
				在程序运行期间,不修改源码对已有方法进行增强。
		优势:
				减少重复代码
				提高开发效率
				维护方便		

2 AOP 的实现方式

				使用动态代理技术

简单案列说明: 动态代理基于接口与子类的实现

定义一个接口
package com.qyy.proxy;

/**
 * @description: 工人接口类
 * @author: Mr.Yang
 **/
public interface IWorker {
    
    

    /*
     * @author Mr.Yang
     * @Description: 基本工人接口
     * @param [money]
     * @return void
     */
    public void basicAct(Float money);

    /*
     * @author Mr.Yang
     * @Description: 技术工人
     * @param [money]
     * @return void
     */
    public  void dangerAct(Float money);
    }
		
-----------------------------------------------------------------------------------------------------
## 定义一个实现类,实现接口
package com.qyy.proxy;

/**
 * @description: 模拟一个劳务公司
 * @author: Mr.Yang
 **/
public class Worker implements IWorker{
    
    

    /*
     * @author Mr.Yang
     * @Description: 基本工人
     * @param [money]
     * @return void
     */
    public void basicAct(Float money){
    
    
        System.out.println("基本工人,拿到" + money+ "开始工作" );
    }


    /*
     * @author Mr.Yang
     * @Description:   技术工人
     * @param [money]
     * @return void
     */
    public  void dangerAct(Float money){
    
    
        System.out.println("技术工人,拿到" + money+ "开始工作" );
    }
}

-----------------------------------------------------------------------------------------------------
通过main函数进行测试(方法增强)

public class Client {
    
    

    public static void main(String[] args) {
    
    
        //早期:直接去家里找
        Actor actor = new Actor();

        //通过经纪公司来找演员

        /**
         * 动态代理
         *  作用:不修改源码的基础上,对已有方法增强
         *  特点:字节码是随用随创建,随用随加载。
         *  基于接口的动态代理:
         *  提供者:JDK官方
         *  要求:被代理对象最少实现一个接口。
         *  涉及的类:Proxy
         *  涉及的方法:newProxyInstance
         *  方法的参数:
         *      ClassLoader:类加载器。负责加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
         *      Class[]:字节码数组。代理对象具有的方法。和被代理对象实现相同的接口。
         *               如果被代理对象本身是一个接口的话,直接把被代理对象存入字节码数组中。
         *               xxx.getClass().getInterfaces() || new Class[]{xxx}
         *               固定写法。
         *      InvocationHandler:如何代理的接口。谁用谁写。用于增强方法的。需要我们自己提供一个该接口的实现类。
         *                         通常情况下可以写成匿名内部类。
         *                         策略模式:
         *                              数据已经有了
         *                              目的明确。
         *                              达成目标的过程即是策略。
         *
         */
        IActor proxyActor = (IActor)Proxy.newProxyInstance(actor.getClass().getClassLoader(), actor.getClass().getInterfaces(),
                new InvocationHandler() {
    
    
                    /**
                     * 此处提供增强的代码
                     * 执行被代理对象的任何方法,都会经过该方法。
                     * @param proxy     代理对象的引用
                     * @param method    当前执行的方法
                     * @param args      当前方法所需的参数
                     * @return          和被代理对象的方法具有相同的返回值
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                        Object rtValue = null;
                        //1.取出当前方法的参数
                        Float money= (Float) args[0];
                        //2.判断方法是什么
                        if("basicAct".equals(method.getName())){
    
    
                            //基本演出:抽取20% 要求一天5000块以上才接
                            if(money > 5000f){
    
    
                                rtValue = method.invoke(actor,money*0.8f);
                            }
                        }
                        if("dangerAct".equals(method.getName())){
    
    
                            //高危演出:抽取10% 要求一天20000块以上才接
                            if(money > 20000f){
    
    
                                rtValue = method.invoke(actor,money*0.9f);
                            }
                        }
                        return rtValue;
                    }
                });


        proxyActor.basicAct(10000f);
        proxyActor.dangerAct(50000f);
------------------------------------------------------------------------------------------------------
打印结果 ;	
基本工人,拿到8000.0开始工作
技术工人,拿到45000.0开始工作
=====================================================================================================



动态代理基子类的实现

	定义一个子类 :
	ackage com.qyy.proxy;

/**
 * @description: 模拟一个劳务公司
 * @author: Mr.Yang
 **/
public class Worker{
    
    

    /*
     * @author Mr.Yang
     * @Description: 基本工人
     * @param [money]
     * @return void
     */
    public void basicAct(Float money){
    
    
        System.out.println("基本工人,拿到" + money+ "开始工作" );
    }


    /*
     * @author Mr.Yang
     * @Description:   技术工人
     * @param [money]
     * @return void
     */
    public  void dangerAct(Float money){
    
    
        System.out.println("技术工人,拿到" + money+ "开始工作" );
    }
}



通过main函数进行代理测试方法增强()


package com.qyy.cglib;
public class Client {
    
    
    public static void main(final String[] args) {
    
    
  	l Worker worker = new Worker();
   **
         * 动态代理
         *  作用:不修改源码的基础上,对已有方法增强
         *  特点:字节码是随用随创建,随用随加载。
         *  基于子类的动态代理:
         *  提供者:第三方cglib库
         *  要求:被代理对象不能是最终类。不能被final修饰
         *  涉及的类:Enhancer
         *  涉及的方法:create
         *  方法的参数:
         *      Class:字节码。被代理对象的字节码。固定写法。

         *      Callback:如何代理的接口。谁用谁写。用于增强方法的。需要我们自己提供一个该接口的实现类。
         *                         通常情况下可以写成匿名内部类。
         *                         我们需要使用它的子接口:MethodInterceptor
         *                         策略模式:
         *                              数据已经有了
         *                              目的明确。
         *                              达成目标的过程即是策略。
         *
         */
        Worker workerCglib= (Worker )Enhancer.create(actor.getClass(), new MethodInterceptor() {
    
    
         /**
             * 此处提供增强的代码
             * 执行被代理对象的任何方法,都会经过该方法。
             * @param proxy         代理对象的引用
             * @param method        当前执行的方法
             * @param args          当前方法所需的参数
             * @param methodProxy   当前方法的代理对象
             * @return              和被代理对象的方法具有相同的返回值
             * @throws Throwable
             */
         public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    
    
             Object rValue = null;
             // 取出被代理对象的参数
             Float money = (Float) args[0];
             //判断被代理对象的中方法,进行增强
             if ("basicAct".equals(method.getName())){
    
    
                 if (money > 800f){
    
    
                     rValue =   method.invoke(worker,money*0.8f);
                 }
             }
             if ("dangerAct".equals(method.getName())){
    
    
                 if (money>3000f){
    
    
                     rValue =   method.invoke(worker,money*0.9f);
                 }
             }
             return rValue;
         }
     });
  workerCglib.basicAct(50000f);
  workerCglib.dangerAct(50000F);
    }
}


猜你喜欢

转载自blog.csdn.net/weixin_43183496/article/details/105839403