前面说到ProxyFactory
是将SpringAOP中几个元素整合起来的功臣,但是我们看看他所继承的ProxyCreatorSupport
主要有三个具体的分支,用来在不同的场景:
根据名字可以看出另外两个
1、ProxyFactoryBean
容器中的织入器
2、AspectJProxyFactory
对AspectJ的支持,编程式或注解
ProxyFactoryBean
对SpringAOP的使用,更多的时候是结合Spring容器来发挥他的优势。而这一点,我们之前介绍的ProxyFactory
更多偏向于编程式的实现。而与容器的整合这就是ProxyFactoryBean
所做的事情。
首先他继承了FactoryBean
,那么就有了作为容器的特性。我们知道FactoryBean
有一个很重要的方法来注入实现类叫
T getObject() throws Exception;
我们来看看具体的实现方法
public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
这里对singleton
属性是否设置为true
来进行分开的处理,如果为true
会通过内部的singletonInstance
进行缓存:
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
而这里方法getProxy
为实际获取代理对象,这个应该和之前ProxyFactory
的实现类似:
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
而如果为false
则每次都新建实例,具体见方法newPrototypeInstance
起底层仍然使用了上面的getProxy
方法
接下来看看具体的使用,按照之前我们编程式的方法,应该需要注入advisor、interface等
1、interceptorNames
指定植入的advisor
2、proxyInterfaces
如果是基于接口的代理,通过这个列表类型设置。另外如果没有指定有autodetectInterfaces
来自动检测接口,默认为true
3、target
设置目标target,封装为SingletonTargetSource
对象
4、proxyTargetClass
设置是否强制代理class
,默认问false
。如果为true依赖cglib
代理
下面是一个对目标类为class的进行代理了
<bean id="simpleBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="org.java.codelib.spring.aop.pointcut.SimpleBean" />
</property>
<property name="interceptorNames">
<list>
<idref bean="methodMatchPintcut" />
</list>
</property>
<property name="proxyTargetClass" value="true" />
</bean>
<bean id="methodMatchPintcut"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="simpleBeanAdvisor" />
<property name="mappedName" value="sayHi" />
</bean>
<bean id="simpleBeanAdvisor" class="org.java.codelib.spring.aop.pointcut.SimpleAdvice" />
但是这样配置是不是很繁琐,如果有多个需要代理的target该如何办?按照我们一贯的想法一般该有支持正则或是模糊匹配。是的,这个时候就需要自动化代理
>自动化代理的实现是基于BeanPostProcessor
的概念之上,在IOC容器注册完Bean后,通过扫描bean来干预其实例化
主要的自动代理的实现类有BeanNameAutoProxyCreator
、DefaultAdvisorAutoProxyCreator
和AspectJAwareAdvisorAutoProxyCreator
1、BeanNameAutoProxyCreator
<bean id="simpleBean" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<bean class="xxx.SimpleBean1" />
<bean class="xxx.SimpleBean2" />
</property>
<property name="interceptorNames">
<list>
<idref bean="methodMatchPintcut" />
</list>
</property>
</bean>
其中beanNames也可以更简洁的使用*
通配
<property name="beanNames">
<value>simple*,*Service,target*</value>
</property>
2、DefaultAdvisorAutoProxyCreator 这个属于全自动代理的范畴了,只需要在IOC容器中注册就会自动代理
AspectJAwareAdvisorAutoProxyCreator
这个需要详细讲解,根据名字就可以推断是对AspectJ
的自动代理。更多时候我们使用它的一个子类AnnotationAwareAspectJAutoProxyCreator
来完成我们需要的工作。关于AspectJ
和SpringAOP后面做详细的介绍。我们前面说了ProxyFactory
和容器的ProxyFactoryBean
。同样,这里也有AspectJProxyFactory
来编程式的支持,用起来是这样的:
AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
proxyFactory.setProxyTargetClass(true);
proxyFactory.setTarget(new SimpleBean());
proxyFactory.addAspect(LoggingAnnoAspect.class);
SimpleBean proxyBean = (SimpleBean) proxyFactory.getProxy();
proxyBean.sayHi("Robin");
proxyBean.sayHi();
proxyBean.greet();
或者基于AnnotationAwareAspectJAutoProxyCreator
的自动代理,配置文件如下
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="simpleBean" class="org.java.codelib.spring.aop.pointcut.SimpleBean" />
<bean id="logAspect"
class="org.java.codelib.spring.aop.pointcut.aspectj.LoggingAnnoAspect" />
更多内容见这里,接下来我们先介绍AspectJ
,回头再具体介绍AnnotationAwareAspectJAutoProxyCreator
的用法