DefaultSingletonBeanRegistry

DefaultSingletonBeanRegistry

类DefaultSingletonBeanRegistry源码文档解释
英文注释分别阐述了以下内容(一个段落用一个小标):
⑴、类DefaultSingletonBeanRegistry实现了接口SingletonBeanRegistry,是通用注册表的基础实现类:
①、它允许注册bean对象实例(这些对象实例都是单例模式)。
②、已经注册的bean对象实例是注册表的所有调用者共享的(所以特别需要注意线程安全)。
③、可以通过bean名称获得目标bean对象实例。
⑵、类DefaultSingletonBeanRegistry还支持类DisposableBean对象实例的注册(在关闭注册表时销毁),该实例可能与已注册的bean对象实例相对应。bean对象实例之间的依赖关系也可以注册,以此控制销毁bean对象实例的顺序。
⑶、类DefaultSingletonBeanRegistry主要作为实现接口BeanFactory的基类,它分解了单例bean对象实例的常见管理(比如注册,获取等等,但不包含创建)。
①、另一个接口ConfigurableBeanFactory扩展了接口SingletonBeanRegistry。
⑷、类DefaultSingletonBeanRegistry与类AbstractBeanFactory和类DefaultListableBeanFactory(继承自类DefaultSingletonBeanRegistry)相比,既不涉及bean对象实例概念的定义也不涉及bean对象实例的创建过程,还可以用作委托的嵌套助手(涉及Java设计模式)。

 public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry   
 implements SingletonBeanRegistry {
   
    //单例bean对象实例都存储在Map中,但Map不允许存储null
    //所以当bean为null时,就用NULL_OBJECT代替null存储到Map中
	protected static final Object NULL_OBJECT = new Object();
	//日志对象,供子类使用
	protected final Log logger = LogFactory.getLog(getClass());
	//存储已经创建完毕的单例bean对象实例
	//(创建完毕是指构造方法已经执行
	//并且属性也已经根据配置文件赋值完毕)
	//singletonObjects也称为三级缓存
	private final Map<String, Object> singletonObjects = new 
	ConcurrentHashMap<String, Object>(256);
	//存储创建单例bean对象实例的工厂对象实例
	//一个工厂对象实例创建一种类型bean
	//具体的创建过程在类DefaultListableBeanFactory中
	//所有的工厂类都需要implements接口ObjectFactory<?>
	//singletonFactories也称为一级缓存(必须先有工厂才能创建bean)
	private final Map<String, ObjectFactory<?>> singletonFactories = 
	new HashMap<String, ObjectFactory<?>>(16);
	//Spring创建bean对象实例大多都是调用默认构造函数
	//再通过set方法为属性赋值
	//存储已经执行默认构造函数但未给属性赋值的对象
	//earlySingletonObjects也称为二级缓存
	//主要解决bean之间循环依赖的问题
	//(需要明白循环依赖问题后面的源码才能看的懂)
	//Spring中的循环依赖有三种:
	//①、类A类B互为构造方法依赖
	//这种依赖Spring无法解决:创建类A对象的时候
	//发现类A的构造方法参数为类B对象,这时候需要
	//创建类B对象,但是又发现类B的构造方法参数为类A对象
	//结果类A和类B对象都无法创建
	//②、类A的构造方法参数为类B对象,类B的某个
	//setter方法参数为类A对象,创建类A对象的时候
	//需要创建类B对象可以直接通过类B的默认构造方法
	//类B对象创建完毕后类A对象的创建过程得以继续
	//这时类B对象需要暂时放入earlySingletonObjects缓存中
	//因为它只创建了对象,并未给属性赋值
	//③、类A类B互为setter方法参数依赖,举例与第二种
	//情况类似,都是通过默认构造方法创建对象
	//这时类A与类B都会被放入earlySingletonObjects缓存中
	private final Map<String, Object> earlySingletonObjects = 
	new HashMap<String, Object>(16);
	//存储已经创建完毕的单例bean对象实例的名称
	//(创建完毕是指构造方法已经执行
	//并且属性也已经根据配置文件赋值完毕)
	//存储的顺序是单例bean对象实例的注册顺序
	private final Set<String> registeredSingletons = 
	new LinkedHashSet<String>(256);
	//存储正在创建的bean对象实例的名称
	//(正在创建是指构造方法已经执行
	//所有或者部分属性还未根据配置文件赋值)
	private final Set<String> singletonsCurrentlyInCreation =
	Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
	//
	private final Set<String> inCreationCheckExclusions =
	Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
	//禁止的异常,可用于关联相关原因
	private Set<Exception> suppressedExceptions;
	//指示我们当前是否在destroySingletons中的标志
	private boolean singletonsCurrentlyInDestruction = false;
	
	private final Map<String, Object> disposableBeans = 
	new LinkedHashMap<String, Object>();
	
	private final Map<String, Set<String>> containedBeanMap = 
	new ConcurrentHashMap<String, Set<String>>(16);
	
	private final Map<String, Set<String>> dependentBeanMap = 
	new ConcurrentHashMap<String, Set<String>>(64);
	
	private final Map<String, Set<String>> dependenciesForBeanMap = 
	new ConcurrentHashMap<String, Set<String>>(64);
	//在注册表(Map)中注册一个已经创建完毕的单例bean
	//对象实例singletonObject,名称为指定名称beanName
    public void registerSingleton(String beanName, Object singletonObject) 
    throws IllegalStateException {
   
       //保证指定名称beanName不为null
	   Assert.notNull(beanName, "'beanName' must not be null");
	   //因为注册表中的单例bean对象实例是它的所有调用者共享的
	   //所以在多线程环境下同一时间内只能有一个调用者操作
	   //singletonObjects,需要通过关键字synchronized保证线程安全
	   synchronized (this.singletonObjects) {
   
	      //判断指定名称beanName是否已经注册,通过它
	      //去一级缓存中获取对象
	      Object oldObject = this.singletonObjects.get(beanName);
	      //如果oldObject != null,说明beanName已经注册
		  if (oldObject != null) {
   
		     //直接抛出异常,并提示已注册的名称不能重复注册
		     //因为Map的key是唯一的
		     throw new IllegalStateException("Could not register object 
		     [" + singletonObject +"] under bean name '" + beanName + "': 
		     there is already object [" + oldObject + "] bound");
		  }
		  //如果oldObject == null,说明beanName未注册
		  //继续执行注册流程,参考方法
		  //addSingleton(String beanName, Object singletonObject)
		  addSingleton(beanName, singletonObject);
	   }
	}
	//向注册表的一级缓存中添加已经
	//创建完毕的单例bean对象实例singletonObject
	protected void addSingleton(String beanName, Object singletonObject) {
   
	   //保证线程安全
	   synchronized (this.singletonObjects) {
   
	      //向一级缓存中添加键值对beanName->singletonObject
	      //因为Map不允许添加null,如果singletonObject == null
	      //就用NULL_OBJECT代替
	      this.singletonObjects.put(beanName, (singletonObject != null ? 
	      singletonObject : NULL_OBJECT));
	      //singletonObject是已经创建完毕的单例bean对象实例
	      //所以三级缓存中的记录需要删除
	      //(如果有,如果没有,remove()不会执行任何操作)
	      //从另一个角度理解:因为是单例,既然已经有已经创建完毕的
	      //singletonObject,自然不再需要创建的工厂,所以删除
		  this.singletonFactories.remove(beanName);
		  //同样,二级缓存中的记录也需要删除
	      //(如果有,如果没有,remove()不会执行任何操作)
		  this.earlySingletonObjects.remove(beanName);
		  //将beanName添加到存储已经创建完毕的
		  //单例bean实例对象的名称集合中
		  //在添加三级缓存的方法addSingletonFactory
		  //(String beanName, ObjectFacto
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java-struts2.2的驱动包 2009-8-29 14:02:04 org.apache.catalina.core.AprLifecycleListener init 信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jdk1.6.0_10\bin;C:\Program Files\Apache Software Foundation\Tomcat 6.0\bin 2009-8-29 14:02:05 org.apache.coyote.http11.Http11Protocol init 信息: Initializing Coyote HTTP/1.1 on http-80 2009-8-29 14:02:05 org.apache.catalina.startup.Catalina load 信息: Initialization processed in 2997 ms 2009-8-29 14:02:05 org.apache.catalina.core.StandardService start 信息: Starting service Catalina 2009-8-29 14:02:05 org.apache.catalina.core.StandardEngine start 信息: Starting Servlet Engine: Apache Tomcat/6.0.16 2009-8-29 14:02:11 org.apache.catalina.core.StandardContext addApplicationListener 信息: The listener "org.springframework.web.context.ContextLoaderListener" is already configured for this context. The duplicate definition has been ignored. log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader). log4j:WARN Please initialize the log4j system properly. 2009-8-29 14:02:12 org.apache.catalina.core.ApplicationContext log 信息: Loading Spring root WebApplicationContext 2009-8-29 14:02:25 org.apache.catalina.core.StandardContext listenerStart 严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.AbstractMethodError: org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator.postProcessAfterInstantiation(Ljava/lang/Object;Ljava/lang/String;)Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:478) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381) at org.springframework.web.context.support.AbstractRefreshableWebApplicationContext.refresh(AbstractRefreshableWebApplicationContext.java:139) at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:252) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:190) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4350) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525) at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924) at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core.StandardHost.start(StandardHost.java:719) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) at org.apache.catalina.core.StandardService.start(StandardService.java:516) at org.apache.catalina.core.StandardServer.start(StandardServer.java:710) at org.apache.catalina.startup.Catalina.start(Catalina.java:578) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413) Caused by: java.lang.AbstractMethodError: org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator.postProcessAfterInstantiation(Ljava/lang/Object;Ljava/lang/String;)Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:957) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:470) ... 39 more 2009-8-29 14:02:25 org.apache.catalina.core.StandardContext start 严重: Error listenerStart 2009-8-29 14:02:25 org.apache.catalina.core.StandardContext start 严重: Context [/OAProject] startup failed due to previous errors 2009-8-29 14:02:25 org.apache.catalina.core.ApplicationContext log 信息: Closing Spring root WebApplicationContext log4j:WARN No appenders could be found for logger (com.opensymphony.xwork2.config.providers.XmlConfigurationProvider). log4j:WARN Please initialize the log4j system properly. 2009-8-29 14:02:46 org.apache.coyote.http11.Http11Protocol start 信息: Starting Coyote HTTP/1.1 on http-80 2009-8-29 14:02:46 org.apache.jk.common.ChannelSocket init 信息: JK: ajp13 listening on /0.0.0.0:8009 2009-8-29 14:02:46 org.apache.jk.server.JkMain start 信息: Jk running ID=0 time=0/125 config=null 2009-8-29 14:02:46 org.apache.catalina.startup.Catalina start 信息: Server startup in 41293 ms

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值