1.SOFABoot源码解析
1.1 JVM服务代理机制
在SOFABoot中,采用AOP代理方式为JVM服务引用创建本地代理对象。对于AOP代理,主要有两种实现方式:
1. 针对实现接口的类,采用JDK动态代理机制;
2. 针对没有实现接口的类,采用CGLIB动态代理机制;
在SOFABoot中,对于JVM服务类型的服务引用,即可以针对某个接口创建代理对象,也可以针对某个类创建代理对象。
1.1.1 AOP代理之JDK动态代理
针对接口(例如:com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService接口),为其创建JVM服务的AOP代理对象的主要逻辑如下:
1. 创建handler,此处为ServiceProxy抽象类的子类JvmServiceInvoker的实例。该类继承了ServiceProxy,而ServiceProxy实现了org.aopalliance.intercept.MethodInterceptor接口,表示此处创建AOP代理的方法拦截器。该AOP代理拦截器拦截对proxyClass指定的接口(例如: PersonService)的方法调用。
2. 创建AOP代理工厂类org.springframework.aop.framework.ProxyFactory的实例factory;
3. 配置factory:如果javaClass为接口,则factory的interfaces列表中增加javaClass。否则,设置factory的targetClass为javaClass,proxyTarget为true。
4. 把指定的AOP advice实例handler增加到advice链尾部。
5. 调用factory的getProxy方法,为指定服务创建AOP代理对象。由于此处目标类是接口,则使用JDK动态代理技术。Spring使用JDK来生成代理对象,具体的实现代码放在org.springframework.aop.framework.JdkDynamicAopProxy这个类中。JdkDynamicAopProxy 同时实现了AopProxy和InvocationHandler接口,InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。invoke主流程可以简述为:获取可以应用到此方法上的通知链(InterceptorChain),如果有,则应用通知,并执行joinpoint;如果通知链为空,则直接反射执行joinpoint。
以上是使用JDK动态代理机制动态创建JVM服务的AOP代理对象的主要流程。
为了查看Proxy动态生成的代理对象的源文件,必须先导出字节码文件,然后通过反编译工具(如:jad)生成源文件。对于Proxy,导出字节码文件方式为在应用代码开始位置设置sun.misc.ProxyGenerator.saveGeneratedFiles为true:
1. @SpringBootApplication
2. @ImportResource({"classpath*:rpc-starter-example.xml" })
3. public class SofaBootRpcDemoApplication {
4.
5. public static void main(String[] args)throws InterruptedException {
6.
7. System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
8.
9. ConfigurableApplicationContext ac =SpringApplication.run(SofaBootRpcDemoApplication.class, args);
10.
11.
12. }
13. }
注意,需要在工程根目录下,增加 com/sun/proxy目录,否则会报错如下:
1. Exception in thread "main"java.lang.InternalError: I/O exception saving generatedfile:java.io.FileNotFoundException : com\sun\proxy\$Proxy0.class (系统找不到指定的路径。)
2. atsun.misc.ProxyGenerator$1.run(ProxyGenerator.java:336 )
3. atsun.misc.ProxyGenerator$1.run(ProxyGenerator.java:327 )
4. atjava.security.AccessController.doPrivileged( Native Method)
5. atsun.misc.ProxyGenerator.generateProxyClass( ProxyGenerator.java:326)
6. atjava.lang.reflect.Proxy$ProxyClassFactory.apply( Proxy.java:672)
7. atjava.lang.reflect.Proxy$ProxyClassFactory.apply( Proxy.java:592)
8. atjava.lang.reflect.WeakCache$Factory.get( WeakCache.java:244)
9. atjava.lang.reflect.WeakCache.get(WeakCache.java:141 )
10. at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:455 )
11. atjava.lang.reflect.Proxy.newProxyInstance( Proxy.java:738)
以下为PersonService接口的AOP代理对象的源文件: