AOP 工厂对象之ScopedProxyFactoryBean 原理解析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AOP 工厂对象之ScopedProxyFactoryBean 原理解析相关的知识,希望对你有一定的参考价值。

J2EE开发者,对购物车这个概念太熟悉了。存在于Session周期中。今天就说说,如果用Spring管理购物车,怎么处理。

  1. 使用场景

<bean id="cart" class="com.hellojd.jpetstore.domain.model.Cart"   scope="session">
    <aop:scoped-proxy  proxy-target-class="true"/>
</bean>

必须要声明 <aop:scoped-proxy..>

或者 annotation配置

@Scope(value="session",proxyMode= ScopedProxyMode.TARGET_CLASS)
@Component
public class Cart implements Serializable {
...
}

经过上面的配置,就可以在controller中,注入使用了。

接下来,分析spring是如何管理购物车的.

2. 源码分析

2.1 ScopedProxyFactoryBean 类图

技术分享

既然ScopedProxyFactoryBean,是个FactoryBean,就关注下getObject()

public Object getObject() {
   if (this.proxy == null) {
      throw new FactoryBeanNotInitializedException();
   }
   return this.proxy;
}

重点是proxy属性的维护了。在BeanFactoryAware.setBeanFactory接口方法中初始化。

发生时机:普通属性注入之后,InitializingBean.afterPropertiesSet() 和 custom init-method之前

public void setBeanFactory(BeanFactory beanFactory) {
   if (!(beanFactory instanceof ConfigurableBeanFactory)) {
      throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
   }
   ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;

   this.scopedTargetSource.setBeanFactory(beanFactory);

   ProxyFactory pf = new ProxyFactory();
   pf.copyFrom(this);
   pf.setTargetSource(this.scopedTargetSource);

   Class beanType = beanFactory.getType(this.targetBeanName);
   if (beanType == null) {
      throw new IllegalStateException("Cannot create scoped proxy for bean ‘" + this.targetBeanName +
            "‘: Target type could not be determined at the time of proxy creation.");
   }
   if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
      //设置源接口
      pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
   }

   // 为增加DefaultScopedObject能力,增加introduction 
   ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
   pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));

   // Add the AopInfrastructureBean marker to indicate that the scoped proxy
   // itself is not subject to auto-proxying! Only its target bean is.
   pf.addInterface(AopInfrastructureBean.class);

   this.proxy = pf.getProxy(cbf.getBeanClassLoader());
}

技术分享

TargetSource用于获取AOP调用的当前“目标”Target
AbstractBeanFactoryBasedTargetSource基于Spring BeanFactory的实现TargetSource的基类Target
ProxyConfig方便的用于创建代理的超类配置AOP
ProxyFactory编程式AOP代理工厂AOP
ProxyCreatorSupport代理工厂的基类
AOP
AdvisedSupport

代理配置元信息管理基类AOP

AOP
AopProxyFactory创建AOP代理的工厂
ScopedObject用于范围对象的AOP接口
DefaultScopedObject
完成从spring中获取
DelegatingIntroductionInterceptor委托引入拦截器







3.RequestScope VS SessionScope

public class SessionScope extends AbstractRequestAttributesScope {

        public String getConversationId() {
           return RequestContextHolder.currentRequestAttributes().getSessionId();
        }
	@Override
	public Object get(String name, ObjectFactory objectFactory) {
		Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
		synchronized (mutex) {
			return super.get(name, objectFactory);
		}
	}

	@Override
	public Object remove(String name) {
		Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
		synchronized (mutex) {
			return super.remove(name);
		}
	}
	...
}	


or

public abstract class AbstractRequestAttributesScope implements Scope {

   public Object get(String name, ObjectFactory objectFactory) {
      RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
      Object scopedObject = attributes.getAttribute(name, getScope());
      if (scopedObject == null) {
         scopedObject = objectFactory.getObject();
         attributes.setAttribute(name, scopedObject, getScope());
      }
      return scopedObject;
   }

   public Object remove(String name) {
      RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
      Object scopedObject = attributes.getAttribute(name, getScope());
      if (scopedObject != null) {
         attributes.removeAttribute(name, getScope());
         return scopedObject;
      }
      else {
         return null;
      }
   }
   ...
  }



本文出自 “简单” 博客,请务必保留此出处http://dba10g.blog.51cto.com/764602/1929157

以上是关于AOP 工厂对象之ScopedProxyFactoryBean 原理解析的主要内容,如果未能解决你的问题,请参考以下文章

循序渐进之Spring AOP - 原理

003 代理工厂

Spring之IOC

Spring--IoC&AOP

Spring系列之AOP分析之对目标对象的拦截过程

动手实现AOP