10.7 自定义Scope
如果用户觉得Spring内置的几种Scope不能满足需求,则可以定制自己的Scope,即实现自己的org.springframework.beans.factory.config.Scope
。Scope接口定义了如下几个方法,详情请参看Spring的API文档。
public interface Scope {
Object get(String name, ObjectFactory<?> objectFactory);
Object remove(String name);
void registerDestructionCallback(String name, Runnable callback);
Object resolveContextualObject(String key);
String getConversationId();
}
下面来看一下Spring内部Scope为application的定义,即ServletContextScope
的定义。
public class ServletContextScope implements Scope, DisposableBean {
private final ServletContext servletContext;
private final Map<String, Runnable> destructionCallbacks = new LinkedHashMap<String, Runnable>();
/**
* Create a new Scope wrapper for the given ServletContext.
* @param servletContext the ServletContext to wrap
*/
public ServletContextScope(ServletContext servletContext) {
Assert.notNull(servletContext, "ServletContext must not be null");
this.servletContext = servletContext;
}
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Object scopedObject = this.servletContext.getAttribute(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
this.servletContext.setAttribute(name, scopedObject);
}
return scopedObject;
}
@Override
public Object remove(String name) {
Object scopedObject = this.servletContext.getAttribute(name);
if (scopedObject != null) {
this.servletContext.removeAttribute(name);
this.destructionCallbacks.remove(name);
return scopedObject;
}
else {
return null;
}
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
this.destructionCallbacks.put(name, callback);
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
/**
* Invoke all registered destruction callbacks.
* To be called on ServletContext shutdown.
* @see org.springframework.web.context.ContextCleanupListener
*/
@Override
public void destroy() {
for (Runnable runnable : this.destructionCallbacks.values()) {
runnable.run();
}
this.destructionCallbacks.clear();
}
}
10.7.1 注册
自定义了Scope之后我们得在Spring中进行注册,好让Spring能够对其进行识别,这样我们才能在进行对应bean定义的时候使用自定义的Scope。自定义Scope的注册有两种方式,一种是程序化的,一种是通过XML进行配置的。
我们先来实现一个自定义的Scope供注册自定义Scope使用。
public class MyScope implements Scope {
private Map<String, Object> beanMap = new ConcurrentHashMap<String, Object>();
/**
* 获取指定beanName的bean实例
* @param name 对应bean的beanName
* @param objectFactory 可以产生对应bean实例的ObjectFactory
* @return 获取到的实例
*/
public Object get(String name, ObjectFactory<?> objectFactory) {
System.out.println("------------get-----------" + name);
synchronized (this) {
if (!beanMap.containsKey(name)) {
System.out.println("-----------not--exists-------" + name);
beanMap.put(name, objectFactory.getObject());
}
}
return beanMap.get(name);
}
/**
* 底层移除name对应的对象。实现者需要同时移除注册的销毁化回调方法
* @param name
* @return 移除的对象
*/
public Object remove(String name) {
return beanMap.remove(name);
}
/**
* 注册一个销毁时的回调方法
* @param name
* @param callback
*/
public void registerDestructionCallback(String name, Runnable callback) {
}
public Object resolveContextualObject(String key) {
return null;
}
public String getConversationId() {
return null;
}
}
程序化注册自定义Scope是通过ConfigurableBeanFactory的registerScope()方法进行的,其对应定义如下,scopeName表示我们需要注册的scope的名称,第二个参数Scope表示我们需要注册的Scope的一个实例。
/**
* Register the given scope, backed by the given Scope implementation.
* @param scopeName the scope identifier
* @param scope the backing Scope implementation
*/
void registerScope(String scopeName, Scope scope);
我们可以通过常用的ApplicationContext,如ClassPathXmlApplicationContext等的getBeanFactory()方法就能获取到对应的ConfigurableBeanFactory对象,然后进行注册。如:
ClassPathXmlApplicationContext context = ...;
context.getBeanFactory().registerScope("myScope", new MyScope());
通过XML配置进行注册是指通过在Spring的配置文件中定义一个CustomScopeConfigurer类型的bean,并通过其setScopes()方法注入自定义Scope。如下所示,我们通过XML配置注册了一个名叫myScope的Scope定义。
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myScope">
<bean class="com.app.MyScope"/>
</entry>
</map>
</property>
</bean>
之后就可以在定义bean的时候使用我们自己定义的myScope来作为bean定义的Scope了。
<bean id="hello" class="com.app.Hello" scope="myScope"/>
在上述配置中我们指定了id为hello的bean定义的scope为自定义的myScope。之后运行如下测试代码,我们可以看到控制台的输出过程。我们每从bean容器中获取一次hello的实例,对应MyScope的get()方法就会被调用一次。
@org.junit.Test
public void test() {
System.out.println(context.getBean("hello"));
System.out.println(context.getBean("hello"));
}
(注:本文是基于Spring4.1.0所写)
相关推荐
此外,Spring还提供了自定义Scope的机制,开发者可以根据需求定义自己的Bean作用域。 为了深入学习这个主题,可以参考提供的博文链接(虽然这里没有给出具体的链接内容,通常这些链接会包含博主的个人理解和实践...
它解析`<bean>`标签,从中提取出`class`属性(定义bean的实现类)、`parent`属性(定义父bean)、以及其他的属性,如`scope`(作用域)、`abstract`(是否为抽象bean)、`lazy-init`(是否延迟初始化)、`autowire`...
Spring允许开发者定义bean的初始化方法和销毁方法,以实现自定义的生命周期行为。此外,还涉及了bean的生命周期状态,如单例bean的实例化时机以及原型bean的每次请求都会创建新实例等。 2. **Spring_0700_IOC_...
4. **Scope**: Bean的作用域,比如单例(Singleton)、原型(Prototype)等,决定了Bean的实例化策略。 5. **Bean的查找和引用**: 容器提供了获取Bean实例的方法,以及在Bean之间引用其他Bean的能力。 通过分析这...
2.1 Bean 的Scope 30 2.1.1 点睛 30 2.1.2 示例 31 2.2 Spring EL 和资源调用. 33 2.2.1 点睛 33 2.2.2 示例 33 2.3 Bean 的初始化和销毁 37 2.3.1 点睛 37 2.3.2 演示 38 2.4 Profile 40 2.4.1 点睛 40 2.4.2 演示 ...
标题“spring ioc”指的是Spring框架中的核心特性——Inversion of Control(控制反转),也称为依赖注入(Dependency Injection)。在Spring框架中,IOC是通过容器来管理对象的生命周期和对象之间的依赖关系,使得...
本篇我们将聚焦于"Spring学习笔记系列之三"中的关键知识点——SpringMVC的源码分析,特别是父子容器的启动原理。这个主题是理解Spring MVC工作流程、定制化配置以及优化应用程序性能的关键。 首先,我们要明白...
Spring 还支持自定义 Scope,如 Singleton(单例)、Prototype(原型)、Request(请求)、Session(会话)等。 4. **数据访问集成**:Spring 对各种数据访问技术提供了集成,包括 JDBC、JPA、Hibernate、MyBatis ...
此外,`@Autowired`注解用于自动装配bean的依赖,`@Qualifier`用于指定特定的bean,`@Scope`控制bean的作用域,`@PostConstruct`和`@PreDestroy`标记初始化和销毁方法。 **总结** Spring框架的IOC和AOP机制极大地...
2.1 Bean 的Scope 30 2.1.1 点睛 30 2.1.2 示例 31 2.2 Spring EL 和资源调用. 33 2.2.1 点睛 33 2.2.2 示例 33 2.3 Bean 的初始化和销毁 37 2.3.1 点睛 37 2.3.2 演示 38 2.4 Profile 40 2.4.1 点睛 40 2.4.2 演示 ...
《Spring配置文件详解——共五页》 在Java开发领域,Spring框架无疑是最为重要的工具之一,它以其强大的依赖注入和面向切面编程能力,极大地简化了企业级应用的开发。本篇文档将深入探讨Spring配置文件的核心概念,...
2.1 Bean 的Scope 30 2.1.1 点睛 30 2.1.2 示例 31 2.2 Spring EL 和资源调用. 33 2.2.1 点睛 33 2.2.2 示例 33 2.3 Bean 的初始化和销毁 37 2.3.1 点睛 37 2.3.2 演示 38 2.4 Profile 40 2.4.1 点睛 40 2.4.2 演示 ...
- 生命周期管理:包括初始化、正常使用和销毁三个阶段,Spring提供了回调方法、Scope(作用域)和生命周期接口等进行管理。 3. **04依赖注入.xmind** —— 依赖注入的详细操作 - XML配置注入:通过`<bean>`标签...
通过@Scope注解控制Bean的作用域,如单例(singleton)或多例(prototype)。此外,还可以通过BeanPostProcessor和InitializingBean接口自定义Bean的初始化和销毁逻辑。 6. **AOP代理**:Spring支持JDK动态代理和...
此外,还可以通过`scope`属性来指定Bean的作用域。同时,我们还会接触到生命周期回调方法,如`@PostConstruct`和`@PreDestroy`注解,它们允许我们在Bean初始化和销毁时执行特定操作。 在多校园项目的背景下,Spring...
- `@Scope`:定义Bean的作用域,如单例(`singleton`)或原型(`prototype`)。 - `@Lazy`:标记Bean为懒加载,意味着只有在首次请求时才会初始化。 - `@PostConstruct`和`@PreDestroy`:分别标记初始化方法和销毁...
SpringBoot 搭建——整合 Redis 与 MyBatis 的实战指南 在现代的 Java 开发中,Spring Boot 已经成为了快速构建应用的首选框架,它极大地简化了 Spring 应用的初始设置和配置。本教程将详细介绍如何使用 Spring ...
除了基本的bean注解,还有其他一些常用的注解,比如`@Value`用于注入属性值,`@Qualifier`用于在多个相同类型的bean中指定注入哪一个,`@Scope`用于定义bean的作用范围,如单例(singleton)或原型(prototype)等。...