Spring AOP 源码解析系列,建议你们按顺序阅读,欢迎讨论spring
上一章中咱们分析了ProxyFactory,它是Spring AOP核心的底层实现。然而硬编码的方式仍是过于繁琐且不易使用,本章咱们将讨论ProxyFactoryBean,它结合了ProxyFactory和Ioc中的FactoryBean扩展,使得能够经过XML配置的方式来实现Spring AOP。关于Spring AOP建立代理的具体实现本章将不会再赘述,而是主要讨论FactoryBean扩展结合Spring AOP的使用。chrome
我在IOC容器(四)-FactoryBean一篇中已详细地介绍了FactoryBean在Spring IOC中的实现原理,这里仍是简单介绍一下。缓存
FactoryBean顾名思义,工厂Bean,便可以动态建立Bean的Bean。对于一些只有在运行时才能明确的对象来讲,直接在XML中定义已不能知足,而是经过定义一个工厂类,在运行时根据不一样配置来生成最终的对象。框架
FactoryBean是Spring IOC的两大扩展之一(另外一个是BeanPostProcessor),由此与Spring集成的功能众多,包括但不限于AOP,ORM,事务管理,Remoting。ide
简单看下AbstractBeanFactory中对FactoryBean处理的代码this
// 单例 if (mbd.isSingleton()) { // 获取单例的bean对象 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { [@Override](https://my.oschina.net/u/1162528) public Object getObject() throws BeansException { try { // 匿名内部类中建立bean对象 return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } } }); // 处理FactoryBean扩展 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
能够看到,对象建立完成后会判断是否为FactoryBean的子类,若是是,则会调用getObject方法返回真正的对象。编码
回到ProxyFactoryBean,先贴出以前例子的配置。.net
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 原始对象 --> <bean id="chromeBrowser" class="com.lcifn.spring.aop.bean.ChromeBrowser"/> <!-- 环绕加强对象 --> <bean id="browserAroundAdvice" class="com.lcifn.spring.aop.advice.BrowserAroundAdvice"></bean> <bean id="browserProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 接口 --> <property name="interfaces" value="com.lcifn.spring.aop.bean.Browser"/> <!-- 要代理的对象 --> <property name="target" ref="chromeBrowser"/> <!-- 拦截器组 --> <property name="interceptorNames"> <list> <value>browserAroundAdvice</value> </list> </property> </bean> </beans>
基本配置就不说了,按照上面FactoryBean的介绍,Spring建立完ProxyFactoryBean对象后,就会调用其getObject方法。prototype
public Object getObject() throws BeansException { // 初始化Advisor链 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(); } }
getObject方法就作了两件事,一是初始化Advisor链,二是建立代理对象,不过建立代理对象时区分单例和多例。设计
简单地说,就是将配置中的interceptorNames转化成Advisor对象。其中又分为名称精确匹配和名称全局匹配两种,精确匹配就不用说了,全局匹配就是以*号结尾的这种。
对于全局匹配这种,就是在BeanFactory中匹配全部Advisor和Interceptor类型的Bean,再用*前的名称前缀去匹配Bean的名称。
private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) { String[] globalAdvisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class); String[] globalInterceptorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class); List<Object> beans = new ArrayList<Object>(globalAdvisorNames.length + globalInterceptorNames.length); Map<Object, String> names = new HashMap<Object, String>(beans.size()); for (String name : globalAdvisorNames) { Object bean = beanFactory.getBean(name); beans.add(bean); names.put(bean, name); } for (String name : globalInterceptorNames) { Object bean = beanFactory.getBean(name); beans.add(bean); names.put(bean, name); } OrderComparator.sort(beans); for (Object bean : beans) { String name = names.get(bean); if (name.startsWith(prefix)) { addAdvisorOnChainCreation(bean, name); } } }
而对于精确匹配的更加清晰,直接取BeanFactory中找,而若是ProxyFactoryBean的singleton属性设置为false时,则封装为PrototypePlaceholderAdvisor延迟建立。
// 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);
两种方式最后都经过addAdvisorOnChainCreation来执行添加操做。其中重要的是将根据name从BeanFactory中得到的对象转换成Advisor,由于interceptorNames支持Advisor,Advice,MethodInterceptor多种类型的对象name,经过namedBeanToAdvisor方法统一转成Advisor类型。
private void addAdvisorOnChainCreation(Object next, String name) { // We need to convert to an Advisor if necessary so that our source reference // matches what we find from superclass interceptors. // 转换Bean对象为Advisor Advisor advisor = namedBeanToAdvisor(next); if (logger.isTraceEnabled()) { logger.trace("Adding advisor with name '" + name + "'"); } addAdvisor(advisor); } private Advisor namedBeanToAdvisor(Object next) { try { return this.advisorAdapterRegistry.wrap(next); } catch (UnknownAdviceTypeException ex) { // We expected this to be an Advisor or Advice, // but it wasn't. This is a configuration error. throw new AopConfigException("Unknown advisor type " + next.getClass() + "; Can only include Advisor or Advice type beans in interceptorNames chain except for last entry," + "which may also be target or TargetSource", ex); } }
这里的advisorAdapterRegistry实现为DefaultAdvisorAdapterRegistry,这个wrap方法也是被多个地方调用以达到统一Advisor,以后方便生成代理拦截器链。
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter. return new DefaultPointcutAdvisor(advice); } for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported. if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); }
建立代理对象时根据singleton属性决定建立的对象是单例仍是多例。咱们以单例的来看
private synchronized Object getSingletonInstance() { if (this.singletonInstance == null) { // 返回targetSource 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; }
freshTargetSource判断targetName为null,直接返回targetSource,不然从beanFactory根据targetName获取target对象。
对于代理接口集合为空,且proxyTargetClass为空时,从targetClass获取其实现的接口集合做为代理接口。于是在配置ProxyFactoryBean时,能够不用指定interfaces属性。
getProxy方法的实现同ProxyFactory一致,都是经过AopProxyFactory->AopProxy->Proxy的方式,具体可见ProxyFactory中的建立代理一节。返回的对象赋予类变量做为单例缓存。
对于多例的状况,调用的newPrototypeInstance方法
private synchronized Object newPrototypeInstance() { ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory()); // The copy needs a fresh advisor chain, and a fresh TargetSource. TargetSource targetSource = freshTargetSource(); copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain()); if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) { // Rely on AOP infrastructure to tell us what interfaces to proxy. copy.setInterfaces( ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader)); } copy.setFrozen(this.freezeProxy); if (logger.isTraceEnabled()) { logger.trace("Using ProxyCreatorSupport copy: " + copy); } return getProxy(copy.createAopProxy()); }
经过建立一个新的基类对象ProxyCreatorSupport,并copy全部配置的方式每次生成一个新的对象,最后经过getProxy方法获取代理对象。
至此ProxyFactoryBean的介绍就结束了,它主要的特色就是使用FactoryBean同IOC进行告终合。你们都知道Spring框架是一种微内核的设计,包括其AOP,事务管理等许多功能都是经过扩展的方式来设计的。而这种设计思想随着深刻到各功能源码,包括一些其余框架同Spring的整合,不能不说这是Spring生态繁荣的一个重要缘由。