一、自定义作用域需要实现Scope接口
这块实现的作用域是线程级别的
package com.sunshine.boot.common;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 控制bean的作用域是线程级别的
*/
public class CustomThreadScope implements Scope {
public static final String THREAD_SCOPE = "thread";
private ThreadLocal<Map<String, Object>> beanMapThreadLocal = new ThreadLocal() {
@Override
protected Object initialValue() {
return new HashMap<>();
}
};
/**
* 返回当前作用域中name对应的bean对象
* name:需要检索的bean的名称
* objectFactory:如果name对应的bean在当前作用域中没有找到,那么可以调用这个ObjectFactory来创建这个对象
**/
@Override
public Object get(String s, ObjectFactory<?> objectFactory) {
Object bean = beanMapThreadLocal.get().get(s);
if(bean == null) {
bean = objectFactory.getObject();
beanMapThreadLocal.get().put(s,bean);
}
return bean;
}
/**
* 将name对应的bean从当前作用域中移除
**/
@Override
public Object remove(String s) {
return this.beanMapThreadLocal.get().remove(s);
}
/**
* 用于注册销毁回调,如果想要销毁相应的对象,则由Spring容器注册相应的销毁回调,
* 而由自定义作用域选择是不是要销毁相应的对象
*/
@Override
public void registerDestructionCallback(String s, Runnable runnable) {
//bean作用域范围结束的时候调用的方法,用于bean清理
System.out.println(s);
}
/**
* 用于解析相应的上下文数据,比如request作用域将返回request中的属性。
*/
@Override
public Object resolveContextualObject(String s) {
return null;
}
/**
* 作用域的会话标识,比如session作用域将是sessionId
*/
@Override
public String getConversationId() {
return null;
}
}
二、创建bean的实体
package com.sunshine.boot.DTO;
import com.sunshine.boot.common.CustomThreadScope;
import lombok.Data;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("threadBean")
@Scope(CustomThreadScope.THREAD_SCOPE)
public class BeanScopeItem {
}
三、测试
package com.sunshine.boot.common;
import com.sunshine.boot.BootTest01;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
public class CustomThreadScopeTest {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(BootTest01.class, args);
context.getBeanFactory().registerScope(CustomThreadScope.THREAD_SCOPE,new CustomThreadScope());
for(int i = 0; i < 2; i++) {
new Thread(() -> {
Object threadBean = context.getBean("threadBean");
System.out.println(Thread.currentThread() + "," + context.getBean("threadBean"));
// 若不执行下面这行代码 threadBean和threadBean1是同一个对象 即bean的作用域是线程级别的
// 若执行下面这行代码 threadBean和threadBean1不是同一个对象
// context.getBeanFactory().destroyScopedBean("threadBean");
Object threadBean1 = context.getBean("threadBean");
System.out.println("threadBean和threadBean1是否相等:" + (threadBean == threadBean1));
System.out.println(Thread.currentThread() + "," + context.getBean("threadBean"));
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}