序:代理对象的创建
无论是AspecJProxyFactory
、ProxyFactoryBean
、ProxyFactory
大体逻辑都是:
- 填充
ProxyCreatorSupport
,实际上它是Advised
子类,即填充代理配置类;
- 得到JDK或者CGLIB的AopProxy;
- Proxy Bean被调用时,被invoke或intercept方法拦截,并且会调用
ProxyCreatorSupport(AdvisedSupport)
的getInterceptorsAndDynamicInterceptionAdvice
方法去初始化advice和各个方法上的拦截器链并缓存。
上述三个类本身并没有什么关系,但是都继承自ProxyCreatorSupport
,创建代理对象的核心就是在ProxyCreatorSupport
中实现的。
一、通过ProxyFactoryBean配置
FactoryBean目的是构建复杂的Bean对象,而ProxyFactoryBean
的getObject()
最终产生的便是Proxy Bean。
配置类:
@Configuration
public class MyConfig {
@Bean
public LogMethodBeforeAdvice logMethodBeforeAdvice() {
return new LogMethodBeforeAdvice();
}
@Bean("tService")
public TService tService() {
return new TService();
}
@Bean("proxyFactoryBean")
public ProxyFactoryBean proxyFactoryBean(TService tService) {
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
//代理的目标对象,效果等效于setTargetSource()
proxyFactoryBean.setTarget(tService);
//设置`String[] interceptorNames`,以便后续初始化"拦截器链"。
proxyFactoryBean.setInterceptorNames("logMethodBeforeAdvice");
return proxyFactoryBean;
}
}
拦截器类:
public class LogMethodBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("this is logMethodBeforeAdvice!");
}
}
目标类:
public class TService {
public void run1(){
System.out.println("This is a run1() Method!");
}
}
测试类:
public class TestProxy {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
//可以使用@Primary指定元素,或直接使用name名获取。
//Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException:
// No qualifying bean of type 'com.tellme.Impl.proxy.TService' available:
// expected single matching bean but found 2: tService,proxyFactoryBean。(或生成两个Bean名字)
//TService bean = applicationContext.getBean(TService.class);
//若使用Class获取Bean,会获取到两个Bean对象。
TService bean = (TService)applicationContext.getBean("proxyFactoryBean");
bean.run1();
System.out.println(bean.getClass());
}
}
结果:
this is logMethodBeforeAdvice!
This is a run1() Method!
class com.tellme.Impl.proxy.TService$$EnhancerBySpringCGLIB$$6ac1bfc1
如测试案例所示,构建ProxyFactoryBean
的过程实际上是完成的是代理配置
。即填充Advised
对象。而Advised对象实际上是由多个Advisor
组成。
而ProxyFactoryBean
便是借助于控制反转
,只是传入Interceptors
类名便完成拦截对象的填充。
ProxyFactoryBean实际上实现的是FactoryBean
接口,那么产生的Bean是getObject
方法返回的。而getObject
便完成代理对象的创建过程。
1.1 初始化AdvisorChain
代理对象的创建,首先要创建配置对象,即实现Advised
接口,Spring实现了该接口。我们最终通过ProxyCreatorSupport
提供的API便可以完成配置
配置Advised
,实际上执行的是initializeAdvisorChain()
。
- 在IOC容器中通过BeanName获取到
Advice
对象,(当然这种情况属于单例
,而Spring作为一个框架,实际上会考虑原型
模式以及通配符
的情况)。
- 借助
AdvisorAdapterRegistry
将Advice
转换为Advisor
(当然pointcut是Pointcut.TRUE
,拦截所有的方法)。
- 将
Advisor
加入到AdvicedSupport
维护的列表中。该代理对象会持有所有的Advisor
。
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean