Aop的几个概念:
1.Advice(通知)定义在连接点做什么,为切面增强提供织入接口。在Spring AOP中,主要描述Spring AOP围绕方法调用而注入的切面行为。下图是Advice的类层次图。
2.Pointcut(切点)决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强方法的集合。
3.Advisor(通知器)用来完成对目标方法的切面增强设计(Advice)和关注点设计(Pointcut)的结合。
4.Joinpoint(连接点)程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
首先明确一点,Spring中BeanFactory和FactoryBean的区别,BeanFactory是类工厂,主要方法是getBean(String beanName),而对于FactoryBean而言,用户可以通过该接口的getObject方法定制实例化Bean的逻辑。
AopProxy代理对象的建立
在Spring的AOP模块中,一个主要的部分就是代理对象的生成,而对于Spring应用,可以看到,是通过配置和调用Spring的ProxyFactoryBean来完成这个任务的。在ProxyFactoryBean中封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDK的Proxy和CGLIB两种生成方式。
首先关注一下ProxyFactoryBean的类继承图
ProxyConfig提供了在创建代理过程中需要用到的配置属性。
AdvisedSupport封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象都是一样的,但对于具体的AOP代理对象的建立,AdvisedSupport把它交给具体的子类去完成。
ProxyCreatorSupport是代理工厂的基类,具体的AOP代理对象的生成,根据需要分别由ProxyFactoryBean、AspectJProxyFactory和ProxyFactory来完成。
下面分析一下ProxyFactoryBean是如何生成AopProxy代理对象的。下图是生成AopProxy的大概的顺序图。
首先配置ProxyFactroyBean,如下
从以上配置可以看出,ProxyFactoryBean类有两个重要的成员变量,target和interceptorNames。其中target正是需要进行AOP代理的对象,而interceptorNames则定义好了通知器Advisor。
从FactoryBean获取对象,是以getObject()方法作为入口完成的,对ProxyFactoryBean来说,需要把target目标对象增加的增强处理,都通过getObject方法进行封装。如下代码所示,getObject方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。
public Object getObject() throws BeansException {
initializeAdvisorChain();//初始化Advisor链,在后续的文章中,我们将会来详细介绍通知器的配置
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();
}
}
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;
}
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
这里出现了AopProxy类型的对象,Spring利用这个AopProxy接口类把Aop代理对象的实现与框架的其他部分有效地分离开来。AopProxy接口有两个子类实现,一个是Cglib2AopProxy,另一个是JdkDynamicProxy。
在ProxyCreatorSupport中可以看到,具体的AopProxy是通过AopProxyFactory来生成的。生成代理对象需要的所有信息都封装在AdvisedSupport,这个对象是生成AopProxy的输入参数。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();//用于激活AdivisedSupportListener
}
return getAopProxyFactory().createAopProxy(this);
}
这里AopProxyFactory使用的是DefaultAopProxyFactory,它是在ProxyCreatorSupport中被创建的。于是问题就转换为在DefaultAopProxyFactory中,AopProxy是怎样生成的了。
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()) {
<strong>return new JdkDynamicAopProxy(config);</strong>
}
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
<strong>return CglibProxyFactory.createCglibProxy(config);</strong>
}
else {
return new JdkDynamicAopProxy(config);
}
}
从这段代码可以看出,对于具体的AopProxy对象的生成,最终并没有由DefaultAopProxyFactory来完成,而是由JdkDynamicAopProxy和CglibProxyFactory来完成的。
在JdkDynamicAopProxy中,使用JDK的Proxy类来生成代理对象,首先需要从advised对象中取得代理对象的代理接口配置,然后调用Proxy的newProxyInstance方法,最终得到对应的Proxy代理对象。
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);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
CGLIB生成AopProxy代理对象的过程,这里就不进行分析了,有兴趣的读者可以查看Spring的相关源代码。