Spring架构详解之动态代理的实现原理

前面介绍了Spring容器的构建过程,那Spring能为我们做什么,Spring的Ioc容器又能做什么呢?我们使用Spring必须要首先构建Ioc容器,没有它Spring无法工作,ApplicatonContext.xml就是Ioc 容器的默认配置文件,Spring的所有特性功能都是基于这个Ioc容器工作的,比如后面要介绍的AOP。

Ioc它实际上就是为你构建了一个魔方,Spring为你搭好了骨骼架构,这个魔方到底能变出什么好的东西出来,这必须要有你的参与。那我们怎么参与?这就是前面说的要了解Spring中那有些扩展点 ,我们通过实现那些扩展点来改变Spring的通用行为。至于如何实现扩展点来得到我们想要的个性结果,Spring中有很多例子,其中AOP的实现就是Spring本身实现了其扩展点来达到了它想要的特性功能 ,可以拿来参考。

要了解Spring的AOP就必须先了解的动态代理的原理,因为AOP就是基于动态代理实现的。动态代理还要从JDK本身说起。

在Jdk的java.lang.reflect包下有个Proxy类,它正是构造代理类的入口。这个类的结构入下:

Bean实例创建流程图
Proxy类结构

从上图发现最后面四个是公有方法。而最后一个方法newProxyInstance就是创建代理对象的方法。这个方法的源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public static Object newProxyInstance(ClassLoader loader,   
  
     Class>  [] interfaces, 
  
     InvocationHandler h)   
  
     throws IllegalArgumentException {   
  
      
  
         if (h ==  null ) {   
  
         throw new NullPointerException();   
  
    
  
     Class cl = getProxyClass  (loader, interfaces); 
  
     try {   
  
         Constructor cons = cl.getConstructor(constructorParams);   
  
         return (Object) cons.newInstance( new Object[]   { h }); 
  
     catch (NoSuchMethodException e) {   
  
         throw new InternalError(e.toString());   
  
     catch (IllegalAccessException e) {   
  
         throw new InternalError(e.toString());   
  
     catch (InstantiationException e) {   
  
         throw new InternalError(e.toString());   
  
     catch (InvocationTargetException e) {   
  
         throw new InternalError(e.toString());   
  
    
  
}

这个方法需要三个参数:ClassLoader,用于加载代理类的Loader类,通常这个Loader和被代理的类是同一个Loader类。Interfaces,是要被代理的那些那些接口。InvocationHandler,就是用于执行 除了被代理接口中方法之外的用户自定义的操作,他也是用户需要代理的最终目的。用户调用目标方法都被代理到InvocationHandler类中定义的唯一方法invoke中。这在后面再详解。

下面还是看看Proxy如何产生代理类的过程,他构造出来的代理类到底是什么样子?下面揭晓啦。

Bean实例创建流程图
创建代理对象时序图

其实从上图中可以发现正在构造代理类的是在ProxyGenerator的generateProxyClass的方法中。ProxyGenerator类在sun.misc包下,感兴趣的话可以看看他的源码。

假如有这样一个接口,如下:

1
2
3
4
5
6
7
public interface SimpleProxy { 
   
     public void simpleMethod1();   
         
     public void simpleMethod2(); 
  
}

代理来生成的类结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class $Proxy2  extends java.lang.reflect.Proxy  implements SimpleProxy{   
  
     java.lang.reflect.Method m0;   
  
     java.lang.reflect.Method m1; 
  
     java.lang.reflect.Method m2; 
  
     java.lang.reflect.Method m3; 
  
     java.lang.reflect.Method m4; 
  
      
  
     int hashCode(); 
  
     boolean equals(java.lang.Object); 
  
     java.lang.String toString(); 
  
     void simpleMethod1(); 
  
     void simpleMethod2(); 
  
}

这个类中的方法里面将会是调用InvocationHandler的invoke方法,而每个方法也将对应一个属性变量,这个属性变量m也将传给invoke方法中的Method参数。整个代理就是这样实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值