今天闲着没事翻Spring源代码的时候,又看到了InstantiationStrategy这个接口。
这个接口的实现类是用来实例化bean的。看了一下,发现在spring里面有有这个接口的实现层次是这样的:
<<Interface>>InstantiationStrategy
|
|
SimpleInstantiationStrategy
|
|
CglibSubclassingInstantiationStrategy
对于CglibSubclassingInstantiationStrategy,有这么一句注释:
Default object instantiation strategy for use in BeanFactories.
这个与SimpleInstantiationStrategy最大的区别是支持Method Injection. 其中Method Injection的实现
需要依靠Cglib.具体代码就不贴了。总之就是通过Cglib重新生成一个原来的类的子类,在新的类中对需要注入的方法
进行了overwrite.
到了这里,自然而然的也就想到了Cglib在Spring中另外一处重要的应用,那就是aop.
Spring 的aop的代理方式有两种可以选择,一是JdkDynamicProxy,另一个就是CglibProxy.
在aop中bean的代理生成最终发生在DefaultAopProxyFactory这个类中,代码如下:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
return CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
可以看到,当bean中设置proxyTargetClass属性为true,或者bean本什么没有implements任何接口(以及其他一些 比较特殊情况optimize,啊哈我不知道这个optimise是干什么用的),那么将采用cglib的代理方式。否则采用JdkDynamicProxy代理方式。值得注意的是当bean只是一个接口的时候,将采用JdkDynamicProxy方式。
既然说到这里了,就顺便把两种代理方式也比较一下吧。从概念上来说,java 动态代理是通过接口代理的方式,产生一个
和被代理类有相同接口的类。原理就是通过InvocationHandler接口的方式控制对原来的class的method的访问,
在访问前后加入我们自定义的行为。 而cglib则是通过操作字节码的方式生成一个原来的class的subclass.原理也是把我们自定义的MethodInterceptor加入到新生成的类的里面去。