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;
      }
   }
   ...
  }
时间: 2024-12-18 23:38:24

AOP 工厂对象之ScopedProxyFactoryBean 原理解析的相关文章

springboot + aop + Lua分布式限流原理解析

一.什么是限流?为什么要限流?不知道大家有没有做过帝都的地铁,就是进地铁站都要排队的那种,为什么要这样摆长龙转圈圈?答案就是为了 限流 !因为一趟地铁的运力是有限的,一下挤进去太多人会造成站台的拥挤.列车的超载,存在一定的安全隐患.同理,我们的程序也是一样,它处理请求的能力也是有限的,一旦请求多到超出它的处理极限就会崩溃.为了不出现最坏的崩溃情况,只能耽误一下大家进站的时间. 限流是保证系统高可用的重要手段!!! 由于互联网公司的流量巨大,系统上线会做一个流量峰值的评估,尤其是像各种秒杀促销活动

轻量级的.NET对象查找服务和AOP开发框架Netop.Core源码解说(3)--类工厂/对象查找服务

上节谈了谈Netop.Core的对于应用系统的配置信息的处理,对于Netop.Core最核心的服务--类工厂/对象查找服务当然要用到配置服务,等下会说到. 对于NET类工厂/对象查找服务,名气大的有Spring.Net(对应于Java的Spring--号称轻量级中间件),为什么还要再造一个轮子呢?如果说Spring是轻量级的,那Netop.Core就只 能是微量级的,够用就好,学习曲线会大幅下降,学习研究代码的时间也会大幅下降. 够用就好,何乐而不为?况且Netop.Core的类工厂/对象查找服

Spring?IOC设计原理解析:本文乃学习整理参考而来

Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileSystemXmlApplicationContext 的IOC容器流程 1.高富帅IOC解剖 2. 设置资源加载器和资源定位 3.AbstractApplicationContext的refresh函数载入

Mybatis(四):MyBatis核心组件介绍原理解析和源码解读

Mybatis核心成员 Configuration        MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中 SqlSession            作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能 Executor               MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护 StatementHandler 封装了JDBC

MyBatis框架中Mapper映射配置的使用及原理解析(三) 配置篇 Configuration

从上文<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 我们知道XMLConfigBuilder调用parse()方法解析Mybatis配置文件,生成Configuration对象. Configuration类主要是用来存储对Mybatis的配置文件及mapper文件解析后的数据,Configuration对象会贯穿整个Mybatis的执行流程,为Mybatis的执行过程提供必要的配

Android热修复框架AndFix原理解析及使用

一.前言 最近腾讯弄出一个Tinker热修复框架,那么本文先不介绍这个框架,先来介绍一下阿里的一个热修复框架AndFix,这个框架出来已经很长时间了,但是看网上没有太多非常详细的讲解,这里就来做一次分析.正好项目中要使用到.首先这个框架是开源的:https://github.com/alibaba/AndFix 其实在最早的时候我已经分析了阿里的另外一个热修复框架:Dexposed框架,还不了解的同学可以点击这里查看:Dexposed框架原理解析以及使用 当时介绍这个框架的时候发现他的实现原理很

MyBatis框架中Mapper映射配置的使用及原理解析(七) MapperProxy,MapperProxyFactory

从上文<MyBatis框架中Mapper映射配置的使用及原理解析(六) MapperRegistry> 中我们知道DefaultSqlSession的getMapper方法,最后是通过MapperRegistry对象获得Mapper实例: public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory =

MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder

在 <MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用> 的demo中看到了SessionFactory的创建过程: SqlSessionFactory sessionFactory = null; String resource = "mybatisConfig.xml"; try { sessionFactory = new SqlSessionFactoryBuilder().build(Resources .getResourceAsRea

Spring Boot启动原理解析

Spring Boot启动原理解析http://www.cnblogs.com/moonandstar08/p/6550758.html 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏.所以这次博主就跟你们一起一步步揭开SpringBoot的神秘面纱,让它不在神秘. 正文 我们开发任何一个Spring Boot项目,都会用到如下的启动类 从上面代码可以看出,Annotation定义(@Sp