AOP(2):基于接口的动态代理

414 阅读2分钟

定义接口:
接口就相当于桥梁

package com.dynamic.proxy;

public interface ProxyInterface {
    public void sayHello();
    public void sayBye();
}

定义被代理类:
被代理类就是会被增强功能的方法

public class ProxyInterfaceImpl implements ProxyInterface {

    @Override
    public void sayHello() {
        System.out.println("Hello!");
    }

    @Override
    public void sayBye(){
        System.out.println("Good Bye!");
    }
}

定义处理器:

package com.dynamic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class MyProxyInvocationHandler implements InvocationHandler {
    /**
     * 定义被代理的对象
     */
    private  Object proxied = null;
    /**
     * 构造器, 在创建MyInvocationHandler对象时,传入要被代理的对象
     */
    public  MyProxyInvocationHandler(Object proxied){
        this.proxied = proxied;
    }
    /**
     * 所有代理接口的实现类对象的方法在调用时,都会执行invoke方法
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * 对方法进行增强,如对方法sayHello()进行增强
         */
        Object rtInvoke = null;
        if(method.getName().equals("sayHello")){//先判断方法名是否为sayHello
            System.out.println("前置处理:Sally...");
            rtInvoke = method.invoke(proxied, args);
            System.out.println("后置处理:3Q....");
        }
        return rtInvoke;
    }
}

测试动态代理功能:

package com.dynamic.proxy;


import com.dynamic.proxy.impl.ProxyInterfaceImpl;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;

public class ProxyClient {
    @Test
    public void test()  {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("------第一种-------");
                /**
                 * 测试两种方式
                 */
                /*第一种
                 * (5)代理对象调用目标函数
                 * */
                // (1)先获取代理类$Proxy0的class文件, 也可以不写
                System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
                // (2)加载动态代理类(传入要被代理的接口数组, 即要代理哪些接口)
                Class proxyClass = Proxy.getProxyClass(ProxyInterface.class.getClassLoader(), ProxyInterface.class);
                // (3)通过代理类获取到代理类的构造函数,Proxy的构造函数中,有参构造函数为Proxy(InvocationHandler),因此要给构造函数一个
                //      InvocationHandler.class类型的参数类型
                Constructor cst = null;
                try {
                    cst = proxyClass.getConstructor(InvocationHandler.class);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
                // (4)通过构造函数传入自定义的InvocationHandler对象,生产代理对象
                //      先获取被代理对象,再将被代理对象交给自定义的MyInvocationHandler对象
                //      最后将MyInvocationHandler对象传入代理类的构造器,完成代理对象的创建
                //      最后将代理对象强转为接口类型
                //      为什么能强转????因为通过jvm生成的代理对象(反编译javap查看),实现了代理接口
                //      另外,生成的代理类同时继承了Proxy类,并且调用了invoke(,)方法,这个方法便是MyInvocationHandler中
                //      我们自定义的InvocationHandler,也就调用了自定义的sayHello方法
                ProxyInterfaceImpl proxyInterfaceimpl = new ProxyInterfaceImpl();
                MyProxyInvocationHandler myProxyInvocationHandler = new MyProxyInvocationHandler(proxyInterfaceimpl);
                ProxyInterface proxyintfs = null;
                try {
                    proxyintfs = (ProxyInterface) cst.newInstance(myProxyInvocationHandler);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                proxyintfs.sayHello();
            }
        });
        t1.start();
        try {
            t1.join();
        }catch (InterruptedException e){
            e.printStackTrace();
        }

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                /**
                 * 第二种, 直接调用Proxy类的静态方法
                 */
                System.out.println("------第二种-------");
                //要被代理的接口, 传入的接口为数组类型,与上面第一种情况定义的可变参数不同(即...表示0个或多个可变Object参数)
                ProxyInterface proxyIntfs = (ProxyInterface) Proxy.newProxyInstance(ProxyInterface.class.getClassLoader(),
                        new Class[] {ProxyInterface.class}, new MyProxyInvocationHandler(new ProxyInterfaceImpl()));
                proxyIntfs.sayHello();
            }
        });
        t2.start();

        try {
            t2.join();
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}