自定义 Bean 作用域

Spring 实现自定义的 bean 作用域

  • 实现 Scope 接口
  • 调用 AbstractBeanFactory#registerScope 方法
  • bean 配置的地方指定作用域,如 <bean scope=""> 或 @Scope("")

 

以下实现一个线程级别的 bean 的作用域

先看 Scope 接口的实现

/**
 * 线程级别 scope
 * 
 * @author ConstXiong
 */
public class ThreadLocalScope implements Scope {
	
	public static final String SCOPE_NAME = "thread-local";
	
	private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL = new ThreadLocal<Map<String, Object>>() {
		@Override
		protected Map<String, Object> initialValue() {
	        return new HashMap<>();
	    }
	}; 

	@Override
	public Object get(String name, ObjectFactory<?> objectFactory) {
		Map<String, Object> map = THREAD_LOCAL.get();
		Object object = map.get(name);
		if (object == null) {
			object = objectFactory.getObject();
			map.put(name, object);
		}
		return object;
	}

	@Override
	public Object remove(String name) {
		return THREAD_LOCAL.get().remove(name);
	}

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

	@Override
	public Object resolveContextualObject(String key) {
		return THREAD_LOCAL.get().remove(key);
	}

	@Override
	public String getConversationId() {
		return String.valueOf(Thread.currentThread().getId());
	}

}

 

使用 ApplicationContextAware 接口获取 ApplicationContext,在其 BeanFactory 中注册 ThreadLocalScope

/**
 * 注册 ThreadLocalScope
 * 
 * @author ConstXiong
 */
@Component
public class ScopeRegister implements ApplicationContextAware {

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		WebApplicationContext context = (WebApplicationContext)applicationContext;
		DefaultListableBeanFactory beanFactory = ((DefaultListableBeanFactory)context.getAutowireCapableBeanFactory());
		beanFactory.registerScope(ThreadLocalScope.SCOPE_NAME, new ThreadLocalScope());
	}

}

 

bean 配置与 controller

/**
 * controller
 * 
 * @author ConstXiong
 */
@Controller
public class IndexController {
	
	@Autowired
	private ApplicationContext context;
	
	@RequestMapping("thread")
	@ResponseBody
	public String thread() {
		User user = context.getBean("user", User.class);
		return String.format("thread:%s, user:%s", Thread.currentThread().getId(), user);
	}
	
	@Bean
	@Scope(ThreadLocalScope.SCOPE_NAME)
	private static User user() {
		return new User();
	}
	
}

 

这样在页面请求 http://localhost:8080/thread,线程 id 不同,bean id 也不同

 

完整代码:023-spring-bean-custom-scope

 


【Java学习资源】整理推荐

 

 


【Java面试题与答案】整理推荐

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值