0424-java反射/动态代理(spring ioc用到

2020-04-24  本文已影响0人  小咕咕coco

反射

反射机制就是,java运行时环境中的,动态自观自调能力:

具体:(使用方法,原理等
参见链接:https://www.zhihu.com/question/24304289/answer/694344906

代理

代理要实现的是:原类的封装与功能添加(比如在项目现有所有类的方法前后打印日志。

在不修改原代码前提下实现方法:

  1. 编写一个新类,实现和目标类相同的接口+添加新的功能,
  2. 实例化时:目标对象实例作为参数传入构造方法,代理对象的内部方法都通过调用目标类中对应的方法实现

此为静态代理

动态代理:如何动态实现这个过程?(即动态构造代理类并实例化

首先看一下常规的实例创建过程:

动态实现代理,关键在于,如何获取代理类的class对象?(之前是手动创的代理类,加载时生成的class对象

——class对象的信息从哪获取?

:1. 接口拥有代理对象和目标对象共同的类信息

代理类和目标类理应实现同一组接口。
之所以实现相同接口,是为了尽可能保证代理对象的内部结构和目标对象一致,
这样我们对代理对象的操作最终都可以转移到目标对象身上,代理对象只需专注于增强代码的编写
  1. 但是接口是无法创建对象的

——JDK提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类,实现了类对象构造,进而动态代理

  1. Proxy类:构造类对象
  1. InvocationHandler类(代理和目标之间的桥梁
public class ProxyTest {
    public static void main(String[] args) throws Throwable {
        CalculatorImpl target = new CalculatorImpl();
                //传入目标对象
                //目的:1.根据它实现的接口生成代理对象 2.代理对象调用目标对象方法
        Calculator calculatorProxy = (Calculator) getProxy(target);
        calculatorProxy.add(1, 2);
        calculatorProxy.subtract(2, 1);
    }

    private static Object getProxy(final Object target) throws Exception {
        //参数1:随便找个类加载器给它, 参数2:目标对象实现的接口,让代理对象实现相同接口
        Class proxyClazz = Proxy.getProxyClass(target.getClass().getClassLoader(), target.getClass().getInterfaces());
        Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
        Object proxy = constructor.newInstance(new InvocationHandler() {
            @Override
      //重写invoke
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName() + "方法开始执行...");
                Object result = method.invoke(target, args);
                System.out.println(result);
                System.out.println(method.getName() + "方法执行结束...");
                return result;
            }
        });
        return proxy;
    }
}
public class ProxyTest {
    public static void main(String[] args) throws Throwable {
        CalculatorImpl target = new CalculatorImpl();
        Calculator calculatorProxy = (Calculator) getProxy(target);
        calculatorProxy.add(1, 2);
        calculatorProxy.subtract(2, 1);
    }

    private static Object getProxy(final Object target) throws Exception {
        Object proxy = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),/*类加载器*/
                target.getClass().getInterfaces(),/*让代理对象和目标对象实现相同接口*/
                new InvocationHandler(){/*代理对象的方法最终都会被JVM导向它的invoke方法*/
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println(method.getName() + "方法开始执行...");
                        Object result = method.invoke(target, args);
                        System.out.println(result);
                        System.out.println(method.getName() + "方法执行结束...");
                        return result;
                    }
                }
        );
        return proxy;
    }
}

参考:
https://www.zhihu.com/question/20794107/answer/658139129

上一篇下一篇

猜你喜欢

热点阅读