Sping动态代理源码简单分析

动态代理相关的问题分析:

  1. 动态代理对象可以强制转换成目标对象所实现过的接口类型. 因为代理类也实现了目标类实现过的接口.
  2. InvocationHandler中invoke方法如何执行 ?

结论: 代理对象调用代理方法时,最终会执行到InvocationHandler中的invoke方法.

自己写的测试类

public class ArithmeticCalculatorProxy {
	private Object impl;

	// 创造这个对象时候给被代理类赋值
	public ArithmeticCalculatorProxy(Object impl) {
		this.impl = impl;
	}
	// 创造代理类对象
	public Object getProxy() {
		ClassLoader loader = impl.getClass().getClassLoader();
		Class[] interfaces = impl.getClass().getInterfaces();
		Object proxyInstance = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				String methodName = method.getName();
				MyLogging.beforeMethod(methodName, args);
				Object invoke = method.invoke(impl, args);
				MyLogging.afterMethod(methodName, invoke);

				return invoke;
			}
		});
		return proxyInstance;
	}

}

源码解析:
InvocationHandler的invoke()的执行顺序:
创建代理对象时当作方法参数传进去 -->
构造器对象调用带有InvocationHandler参数的构造器用于创建代理类对象 -->
创建代理类对象把InvocationHandler传给父类Proxy给h属性赋值–>
代理类执行方法,其实执行的时super.h.invoke()方法.

不变的宗旨:
① 实例方法一定是由对象调用的
② 实例方法一定是由当前类的对象调用的。

过程:
进入Proxy代理类中执行newProxyInstance方法
1). 通过 Proxy.newProxyInstance 创建代理对象时, 传入了一个通过匿名内部类创建好的InvocationHandler类型的对象.==>myH

@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException

2). 在newProxyInstance方法中, 719行获取到了代理类的Class对象, 729行获取到了代理类中带 InvocationHandler参数的构造器 ,

719: Class<?> cl = getProxyClass0(loader, intfs);
729:final Constructor<?> cons = cl.getConstructor(constructorParams);
223: private static final Class<?>[] constructorParams =
        { InvocationHandler.class };//这是constructorParams的值

739行执行代理类中的带InvocationHandler参数的构造器, 将我们传入的myH传到了该构造器中.

739:return cons.newInstance(new Object[]{h});//通过反射创建代理对象并返回

下面的是自定义的代理对象的测试类

public final class $Proxy00 extends Proxy implements ArithmeticCalculator {//继承Proxy,实现被代理类实现的接口
	private static Method m1;
	private static Method m2;
	private static Method m5;
	private static Method m3;
	private static Method m4;
	private static Method m6;
	private static Method m0;

	public $Proxy00(InvocationHandler arg0) throws  {
      super(arg0);//调用这个构造器把InvocationHandler的实现类对象传给Proxy
   }
	
	public final int add(int arg0, int arg1) throws  {
      try {
      //代理类中代理的方法中都有这么一行代码,参数时代理类对象,方法对象,参数
         return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();
      } catch (RuntimeException | Error arg3) {
         throw arg3;
      } catch (Throwable arg4) {
         throw new UndeclaredThrowableException(arg4);
      }
   }
   }

3). 在代理类($ProxyN)中的构造器中,将我们传入的myH通过 super(h)又传入到了父类(Proxy)的构造器中。

public $Proxy00(InvocationHandler arg0) throws  {
      super(arg0);//调用这个构造器把InvocationHandler的实现类对象传给Proxy
   }

4). 在父类(Proxy)的构造器中,将传入的myH 又赋值给了成员变量h . 看266行.

 266:protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

5). 在代理类中的每个代理方法中, 都一行代码 super.h.invoke(代理对象,方法对象,方法参数);

	//执行的传给Proxy的Invocation的实现类的invoke()方法;
    return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(arg0), Integer.valueOf(arg1)})).intValue();

因此, 代理对象调用代理方法时, 会通过代理方法中的super.h.invoke 执行到我们自己创建的myH中的invoke方法

猜你喜欢

转载自blog.csdn.net/laozhang0910/article/details/89333135
0条评论
添加一条新回复