使用ProxyFactoryBean必须使用setTarget或者setTargetName设置被代理对象,否则target对象找不到后续的操作会直接抛出NPE。
setTargetClass并不是用来设置代理对象的,下文将会给出详细解释.
setTargetName("targetName")targetName为被代理对象在BeanFactory中的注册的id.
将ProxyFactoryBean注册到beans.xml中,代码大概是这样的
如果context是一个controller类,那么上面这两个声明的bean都会向HandlerMapping注册路由地址,将会会导致路由地址重复异常。
或者继承ProxyFactoryBean,直接在构造器中setTarget,代码如下:
JDK提供的代理只能用来代理接口,CGLIB则可以生成一个继承指定类的新类。
所以AdvisedSupport(ProxyFactoryBean的父类)提供的setTargetClass,就是用来指定当通过CGLIB代理对象时,新生成的代理对象需要继承的类,
当然这个类必须是代理对象的父类,或者是接口,或是代理对象自身的类(不指定时默认该值)。
当然既然要使用CGLIB那么就一定要setProxyTargetClass(true)开启这个开关。
判断逻辑在DefaultAopProxyFactory中,代码如下
可以看出config.isProxyTargetClass()是判断是否通过CGLIB生成代理类的条件之一。
setTargetClass并不是用来设置代理对象的,下文将会给出详细解释.
setTargetName("targetName")targetName为被代理对象在BeanFactory中的注册的id.
将ProxyFactoryBean注册到beans.xml中,代码大概是这样的
<bean id="context" class="........"/>
<bean id="proxiedBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="context"/>
</bean>
此时工厂中同时存在两个context,只不过proxiedBean是一个被代理的context。
如果context是一个controller类,那么上面这两个声明的bean都会向HandlerMapping注册路由地址,将会会导致路由地址重复异常。
或者继承ProxyFactoryBean,直接在构造器中setTarget,代码如下:
public class ContextProxyFactoryBean extends ProxyFactoryBean {
public ContextProxyFactoryBean() {
Context context = new Context();
setTarget(context);
}
}
Spring的代理机制有两种,JDK提供的动态代理和CGLIB代理
JDK提供的代理只能用来代理接口,CGLIB则可以生成一个继承指定类的新类。
所以AdvisedSupport(ProxyFactoryBean的父类)提供的setTargetClass,就是用来指定当通过CGLIB代理对象时,新生成的代理对象需要继承的类,
当然这个类必须是代理对象的父类,或者是接口,或是代理对象自身的类(不指定时默认该值)。
当然既然要使用CGLIB那么就一定要setProxyTargetClass(true)开启这个开关。
判断逻辑在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() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
可以看出config.isProxyTargetClass()是判断是否通过CGLIB生成代理类的条件之一。