Spring源码阅读-使用ProxyFactoryBean实现AOP

原创
2017/07/03 16:51
阅读数 2.4K

一 例子

通过ProxyFactoryBean实现对Person的代理,不需要修改代码Person,只需要配置:

public interface IPerson {
	public String queryName();
}

public class Person implements IPerson {

	private String name;
	
	public String queryName() {
		System.out.println("name:" + name);
		return name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
public class PersonAdvice implements MethodBeforeAdvice, AfterReturningAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("before......");
	}

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("afterReturning......");
	}
}
<bean id="person" class="com.myframe.modules.test.service.impl.Person">
	<property name="name" value="zhangsan"></property>
</bean> 

<!-- 准备切点跟advice -->
<bean id="beforeAfterAdvice" class="com.myframe.modules.test.service.impl.PersonAdvice">
</bean>
<bean id="queryPointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
	<property name="pattern" value=".*query.*"></property>
</bean>
<bean id="queryAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
	<property name="advice" ref="beforeAfterAdvice"></property>
	<property name="pointcut" ref="queryPointCut"></property>
</bean>

<bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
	<property name="target" ref="person"/>  
 	<property name="interceptorNames" value="queryAdvisor" />  
</bean>

指定ProxyFactoryBean对象名称为personProxy,并指定目标对象和拦截对象,获取的personProxy对象实际上就是一个代理过的对象,调用其方法queryName的到打印结果:

before......
name:zhangsan
afterReturning......

二 源码走读

回顾前面的BeanFactory,获取personProxy对象走到doGetBean方法,doGetBean中获得对象后都会调用一句getObjectForBeanInstance方法,这里是实现代理的核心逻辑,它的核心思想是判断对象是否是FactoryBean,如果是则调用其getObject方法。

上面使用的ProxyFactoryBean是FactoryBean的子类,看它的getObject方法:

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();
	}
}

主要分两步:

1. initializeAdvisorChain

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
	if (this.advisorChainInitialized) {
		return;
	}
	if (!ObjectUtils.isEmpty(this.interceptorNames)) {
		if (this.beanFactory == null) {
			throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) "
					+ "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
		}
		// Globals can't be last unless we specified a targetSource using
		// the property...
		if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX)
				&& this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("Target required after globals");
		}
		// Materialize interceptor chain from bean names.
		for (String name : this.interceptorNames) {
			if (logger.isTraceEnabled()) {
				logger.trace("Configuring advisor or advice '" + name + "'");
			}
			//带通配符的, 就把容器中所有命中的都拿出来
			if (name.endsWith(GLOBAL_SUFFIX)) {
				if (!(this.beanFactory instanceof ListableBeanFactory)) {
					throw new AopConfigException(
							"Can only use global advisors or interceptors with a ListableBeanFactory");
				}
				addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
						name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
			}
			else {
				// If we get here, we need to add a named interceptor.
				// We must check if it's a singleton or prototype.
				Object advice;
				if (this.singleton || this.beanFactory.isSingleton(name)) {
					// Add the real Advisor/Advice to the chain.
					advice = this.beanFactory.getBean(name);
				} else {
					// It's a prototype Advice or Advisor: replace with a
					// prototype.
					// Avoid unnecessary creation of prototype bean just for
					// advisor chain initialization.
					advice = new PrototypePlaceholderAdvisor(name);
				}
				//放到集合中
				addAdvisorOnChainCreation(advice, name);
			}
		}
	}
	this.advisorChainInitialized = true;
}

这边就是将配置的interceptorNames对应的对象初始化好放到advisors集合中,如果带有*结尾的就把beanFactory中所有命中的前缀都加进来,advisorChainInitialized会标记是否已经处理过,保证只会被加载一次。   

2. 实例化

这里以单例模式看代理对象的创建,看方法getSingletonInstance():

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);
		//先获取aop proxy对象
		this.singletonInstance = getProxy(createAopProxy());
	}
	return this.singletonInstance;
}
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	//先获取创建AopProxy的工厂, 再由此创建AopProxy
	return getAopProxyFactory().createAopProxy(this);
}

根据方法调用可以看出先获取AopProxyFactory,然后创建AopProxy,再通过AopProxy创建代理对象。

AopProxyFactory默认就一个实现DefaultAopProxyFactory,看它的createAopProxy方法:

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);
		}
		return new ObjenesisCglibAopProxy(config);
	} else {
		return new JdkDynamicAopProxy(config);
	}
}

这个地方就看出spring是分别什么条件下使用jdk或cglib的动态代理了,总结如下:

  • 如果目标对象实现了接口,默认用jdk proxy,也可以通过配置指定使用cglib
  • 如果目标对象没有实现接口,必须用cglib

下面就是根据两种AopProxy创建代理对象的逻辑了:

如果返回的是JdkDynamicAopProxy则创建代理的方法:

@Override
public Object getProxy() {
	return getProxy(ClassUtils.getDefaultClassLoader());
}

@Override
public Object getProxy(ClassLoader classLoader) {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
	}
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	//标准的jdk proxy用法
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

如果返回的是ObjenesisCglibAopProxy则创建代理的方法:

@Override
public Object getProxy() {
	return getProxy(null);
}

@Override
public Object getProxy(ClassLoader classLoader) {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
	}

	try {
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		if (ClassUtils.isCglibProxyClass(rootClass)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		validateClassIfNecessary(proxySuperClass);
		//创建配置Enhancer
		// Configure CGLIB Enhancer...
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader
					&& ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
		//回调
		Callback[] callbacks = getCallbacks(rootClass);
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// fixedInterceptorMap only populated at this point, after
		// getCallbacks call above
		enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(),
				this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);
		//创建代理
		// Generate the proxy class and create a proxy instance.
		return createProxyClassAndInstance(enhancer, callbacks);
	} catch (CodeGenerationException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass()
				+ "]: " + "Common causes of this problem include using a final class or a non-visible class", ex);
	} catch (IllegalArgumentException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass()
				+ "]: " + "Common causes of this problem include using a final class or a non-visible class", ex);
	} catch (Exception ex) {
		// TargetSource.getTarget() failed
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}

这就是用cglib创建代理对象的范畴了。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部