spring4.3.6源代码 - beans - 编写自己的scope[CustomScopeConfigurer]

37 篇文章 0 订阅
21 篇文章 0 订阅

 

1、编写自己的scope处理器

package cn.java.demo.beantag.customscope;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.weaver.ast.Instanceof;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCreationNotAllowedException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.util.Assert;

/**
 * 自定义作用域
 * @author zhouzhian
 */
public class MySingletonScope implements Scope {
	protected final Log logger = LogFactory.getLog(getClass());
	
	/**
	 * Internal marker for a null singleton object:
	 * used as marker value for concurrent Maps (which don't support null values).
	 */
	protected static final Object NULL_OBJECT = new Object();
	
	/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
	
	/** Flag that indicates whether we're currently within destroySingletons */
	private boolean singletonsCurrentlyInDestruction = false;

	/** Names of beans currently excluded from in creation checks */
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
	
	/** Names of beans that are currently in creation */
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
	
	/** List of suppressed Exceptions, available for associating related causes */
	private Set<Exception> suppressedExceptions;

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
	
	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

	/** Set of registered singletons, containing the bean names in registration order */
	private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
	
	/** 配置的名称 */
	private String scopeNameX = "Unknow";
	public MySingletonScope(){
	}
	public MySingletonScope(String scopeNameX){
		this.scopeNameX = scopeNameX;
	}
	public String getScopeNameX(){
		return scopeNameX;
	}
	
	@Override
	public Object get(String beanName, ObjectFactory<?> objectFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<Exception>();
				}
				try {
					singletonObject = objectFactory.getObject();
					
					if(singletonObject instanceof MySingletonScopeAware){ // 如果实现了感知接口,注入自己
						((MySingletonScopeAware)singletonObject).setMySingletonScope(this);
					}
					
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}

	@Override
	public Object remove(String beanName) {
		return null;
	}

	@Override
	public void registerDestructionCallback(String beanName, Runnable callback) {
		
	}

	@Override
	public Object resolveContextualObject(String key) {
		return null;
	}
	
	@Override
	public String getConversationId() {
		return null;
	}
	
	/**
	 * Callback before singleton creation.
	 * <p>The default implementation register the singleton as currently in creation.
	 * @param beanName the name of the singleton about to be created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
	
	/**
	 * Callback after singleton creation.
	 * <p>The default implementation marks the singleton as not in creation anymore.
	 * @param beanName the name of the singleton that has been created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}

	/**
	 * Add the given singleton object to the singleton cache of this factory.
	 * <p>To be called for eager registration of singletons.
	 * @param beanName the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
}

2、注册自定义scope

<!-- 实现自己的scope,使用自己的scope对象创建bean -->
<bean id="mySingletonScope0"  class="cn.java.demo.beantag.customscope.MySingletonScope">
    <constructor-arg index="0" type="java.lang.String"  name="scopeNameX" value="MySingletonScope0" />
</bean>
<bean id="instancePoolScope0"  class="cn.java.demo.beantag.customscope.InstancePoolScope">
    <constructor-arg index="0" type="java.lang.String"  name="scopeNameX" value="InstancePoolScope0" />
    <property name="maxObjectsCountPerBeanName" value="2" />
</bean>
<bean id="customScopeConfigurer" class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <!-- Spring会自动扫描:实现了BeanFactoryPostProcessor接口 -->
    <property name="scopes">
        <map key-type="java.lang.String" value-type="java.lang.Object">
	 		<entry key="singletonScope0" value="cn.java.demo.beantag.customscope.MySingletonScope" /> <!-- 自己的scope -->
	 		<entry key="singletonScope1" value-ref="mySingletonScope0" /> <!-- 引用单例的scope -->
	 		<entry key="instancePoolScope0" value-ref="instancePoolScope0" /> <!-- 引用单例的scope -->
	 	</map>
    </property>
</bean>

3、使用自定义scope

<bean id="useCustomScopeBean0" scope="singletonScope0" class="cn.java.demo.beantag.bean.UseCustomScopeBean" />  <!-- 使用 singletonScope0 获取bean -->
<bean id="useCustomScopeBean1" scope="singletonScope1" class="cn.java.demo.beantag.bean.UseCustomScopeBean" />  <!-- 使用 singletonScope1 获取bean -->
<bean id="useInstancePoolScopeBean0" scope="instancePoolScope0" class="cn.java.demo.beantag.bean.UseInstancePoolScopeBean" />  <!-- 使用 instancePoolScope0  获取bean -->

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值