bean scope——bean的作用域及注意点
时间:2022-07-22
本文章向大家介绍bean scope——bean的作用域及注意点,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
singleton
注意事项:
- 默认为singleton,即为单例。
- 整个应用共享,需考虑线程安全。
配置方式:
<bean id="" class="" scope="singleton" >或<bean id="" class="" >
prototype
注意事项:
- 需要在scope属性中指定prototype,多例。
- 每次获取时需重新加载。若实例较大,创建时间长、影响系统性能。
配置方式:
<bean id="" class="" scope="prototype">
以下为spring web容器环境中才有
request
注意事项:
- 需要在scope属性中指定request,每次请求创建。
- 由WebApplicationContext接口提供支持。
配置方式:
<bean id="" class="" scope="prototype">
session
注意事项:
- 需要在scope属性中指定session,每个session。
- 由WebApplicationContext接口提供支持。
- session级别共享
配置方式:
<bean id="" class="" scope="session">
application
注意事项:
- 需要在scope属性中指定application,每次请求创建。
- 由WebApplicationContext接口提供支持。
- 一般情况下与singleton相同,一个应用程序可以创建多个spring容器,scope为application时,同名bean一个。
配置方式:
<bean id="" class="" scope="application">
自定义scope
共三步
一、实现Scope接口
package org.springframework.beans.factory.config;
import org.springframework.beans.factory.ObjectFactory;
public interface Scope {
/**
* 返回当前作用域中name所对应的bean对象
* @param name 需要检索的bean名称
* @param objectFactory 没找到的情况下,创建该对象
* @return 找到的对象
*/
Object get(String name, ObjectFactory<?> objectFactory);
/**
* 移除检索到的name对象
* @param name 需要检索的bean名称
* @return 返回删除的对象
*/
Object remove(String name);
/**
* 回调函数,用于销毁响应对象,
* 由Spring容器注册相应的销毁回调
* @param name bean名称
* @param callback 回调函数
*/
void registerDestructionCallback(String name, Runnable callback);
/**
* 解析上下文数据
* @param key 上下文键
* @return 对应对象,若没找到,返回null
*/
Object resolveContextualObject(String key);
/**
* 会话标识
* @return 返回字符串会话标识
*/
String getConversationId();
}
二、自定义scope注册到容器
方法声明片段如下:
package org.springframework.beans.factory.config;
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
//-------------一些代码--------------------------------
/**
* 向容器注册作用域
* @param scopeName 作用域名称
* @param scope 作用域对象
*/
void registerScope(String scopeName, Scope scope);
//-------------一些代码--------------------------------
}
三、使用自定义scope
示例
ThreadScope
mainjavacomshimeathtestdemo1ThreadScope.java
package com.shimeath.test.demo1;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.lang.Nullable;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* TheadScope通过实现Scope接口,自定义scope
* 作用域为一个线程
*/
public class ThreadScope implements Scope {
/**
* 作用域名称为thread,定义bean时可以给scope使用
*/
public static final String THREAD_SCOPE = "thread";
private ThreadLocal<Map<String, Object>> beanMap = new ThreadLocal(){
@Override
protected Object initialValue() {
return new HashMap<>();
}
};
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Object bean = beanMap.get().get(name);
if(Objects.isNull(bean)){
bean = objectFactory.getObject();
beanMap.get().put(name,bean);
}
return bean;
}
@Nullable
@Override
public Object remove(String name) {
return this.beanMap.get().remove(name);
}
/**
* 回调函数,作用域结束时调用,输出name
* @param name
* @param runnable
*/
@Override
public void registerDestructionCallback(String name, Runnable runnable) {
System.out.println(name);
}
@Override
public Object resolveContextualObject(String s) {
return null;
}
@Override
public String getConversationId() {
return Thread.currentThread().getName();
}
}
BeanScopeModel
mainjavacomshimeathtestdemo1BeanScopeModel.java
package com.shimeath.test.demo1;
public class BeanScopeModel {
/**
* 输出当前线程信息
* @param beanScope
*/
public BeanScopeModel(String beanScope){
System.out.println(String.format("线程:%s,create BeanScopeModel,{scope=%s},{this=%s}", Thread.currentThread(), beanScope,this));
}
}
bean配置
mainresourcesbean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="threadBean" class="com.shimeath.test.demo1.BeanScopeModel" scope="thread">
<constructor-arg index="0" value="thread"/>
</bean>
</beans>
测试用例
package com.shimeath.test.demo1;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
public class Client {
public static void main(String[] args) throws InterruptedException {
//导入配置文件
String beanXml = "classpath:bean.xml";
//创建容器,加载bean配置文件
ClassPathXmlApplicationContext context;
context = new ClassPathXmlApplicationContext(beanXml);
context.refresh();
context.getBeanFactory().registerScope(ThreadScope.THREAD_SCOPE, new ThreadScope());
for (int i = 0; i < 2; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread() + "," + context.getBean("threadBean"));
System.out.println(Thread.currentThread() + "," + context.getBean("threadBean"));
}).start();
TimeUnit.SECONDS.sleep(1);
}
}
输出如下
线程:Thread[Thread-1,5,main],create BeanScopeModel,{scope=thread},{this=com.shimeath.test.demo1.BeanScopeModel@770a131f}
Thread[Thread-1,5,main],com.shimeath.test.demo1.BeanScopeModel@770a131f
Thread[Thread-1,5,main],com.shimeath.test.demo1.BeanScopeModel@770a131f
线程:Thread[Thread-2,5,main],create BeanScopeModel,{scope=thread},{this=com.shimeath.test.demo1.BeanScopeModel@a38feba}
Thread[Thread-2,5,main],com.shimeath.test.demo1.BeanScopeModel@a38feba
Thread[Thread-2,5,main],com.shimeath.test.demo1.BeanScopeModel@a38feba
总结
以上结果可以看出,自定义scope生效。不同的线程中的bean均为不同的bean
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Struts2第一天Struts2的概述,Struts2的入门,Struts2常见的配置、Struts2的Action的编写
- SQL 求平均值时去掉极值
- Go 每日一库之 jennifer
- Go 每日一库之 go-cmp
- 孤立森林(Isolation Forest)
- Go 每日一库之 buntdb
- SQL 将多列的数据转到一列
- Go 每日一库之 gjson
- Go 每日一库之 sjson
- SQL 计算累积销售额
- Go 每日一库之 jj
- Struts2第二天:Struts2的数据的封装、结果页面配置
- Go 每日一库之 govaluate
- Go 每日一库之 validator
- Go 每日一库之 gopsutil