ProxyFactoryBean setTarget setTargetName setTargetClass注意事项

使用ProxyFactoryBean必须使用setTarget或者setTargetName设置被代理对象,否则target对象找不到后续的操作会直接抛出NPE。
setTargetClass并不是用来设置代理对象的,下文将会给出详细解释.
setTargetName("targetName")targetName为被代理对象在BeanFactory中的注册的id.
将ProxyFactoryBean注册到beans.xml中,代码大概是这样的


	
此时工厂中同时存在两个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生成代理类的条件之一。

你可能感兴趣的:(spring)