SpringBoot:通过多个Context限制Bean的活动范围
从Spring的包扫描说起
SpringBoot会扫描SpringBootApplication注解标注的类,他所在的包以及这个包的子包,把那里面的Bean注册到applicationContext中,然而,在一个相对大型的项目中,Bean会很多,而且一些框架在starter中会有比较特别的配置(例如Jackson框架)。
那么,我想有没有什么办法可以限制这些Bean的活动范围,让一个模块的Bean仅仅在自己的区域起效,而不会在整个Context内四处乱来。
Spring中有一个父子容器的关系,子容器能够访问父容器,而父容器不能访问子容器,子容器之间当然也是相互隔开的,那么这就是一个很好的实现方法了。
首先,想办法限制父容器的扫描范围,让他不扫描某些Bean,然后使用BeanPostProcessor判别注解,然后根据注解建立子容器,并且扫描子容器的包范围内的Bean,子容器提供一个接口托管到父容器中,所有子容器就可以通过这些在父容器某模块的接口来相互使用其他子容器模块提供的服务,这样Bean就被限制在了自己模块的范围之内了。
初步实现
定义一个注解,用它来描述一个Spring的Bean,待会这个注解会在扫描的时候被排除在外。
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
@Retention(RUNTIME)
@Target(TYPE)
@Component
public @interface SubComp {
}
然后在SpringBootApplication下方标注:
@SpringBootApplication
@ComponentScan(excludeFilters=@Filter(type=FilterType.ANNOTATION,value=SubComp.class))
那么,接下来使用这个注解代替@Component和@Service、@Controller之类的,这样组件就不会被Spring扫描到了。
接下来,定义一个BeanPostProcessor,通过它来查找带有@Configuration的Bean,然后在发现这个注解的时候创建新的AnnotationApplicationContext,然后扫描这个Bean的包,这样,新注解标注的Bean就会被这个Context发现并且注册,最后,让这个Context成为子容器,附属于SpringBootApplication的Context。
@Component
public class RangeProcesser implements BeanPostProcessor,ApplicationContextAware{
private ApplicationContext applicationContext;
private List<ApplicationContext> contexts = new ArrayList<>();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean.getClass().getAnnotation(Configuration.class)!=null) {
AnnotationConfigApplicationContext subContext = new AnnotationConfigApplicationContext(bean.getClass());
subContext.scan(bean.getClass().getPackage().getName());
subContext.start();
subContext.setParent(applicationContext);
contexts.add(subContext);
return null;
}
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.applicationContext = ctx;
}
}
像这样,就有了一些子容器,父子容器关系的特点就是子容器可以访问父容器,反之不可,所以父容器在这里将会提供通用的组件,并且作为子容器相互沟通的桥梁。
未完待续。
SpringBoot:通过多个Context限制Bean的活动范围的更多相关文章
- 尚硅谷springboot学习10-@PropertySource,@ImportResource,@Bean
@PropertySource 使用指定的属性文件而不一定是application.xxx 同样可以注入相关内容 @ImportResource 导入Spring的配置文件,让配置文件里面的内容生效: ...
- springboot根据不同的条件创建bean,动态创建bean,@Conditional注解使用
这个需求应该也比较常见,在不同的条件下创建不同的bean,具体场景很多,能看到这篇的肯定懂我的意思. 倘若不了解spring4.X新加入的@Conditional注解的话,要实现不同条件创建不同的be ...
- SpringBoot配置——@PropertySource、@ImportResource、@Bean
@PropertySource:加载指定的配置文件 package com.hoje.springboot.bean; import org.springframework.beans.factory ...
- SpringBoot框架(4)-- 类装配及Bean装配监听器
1.普通方式装配类对象 (1)添加带有@Bean注解的方法 User.java(带@Component注解) package com.demo.boot.bootenable.beanDemo1 ...
- SpringBoot拦截器中无法注入bean的解决方法
SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ...
- springboot available: expected at least 1 bean which qualifies as autowire candidate奇葩问题
Exception encountered during context initialization - cancelling refresh attempt: org.springframewor ...
- springboot中velocity tool中注入bean
在使用springboo的时候,遇到一个问题,想在tool类中注入一个bean,一直失败,翻了下源码,是因为工具类的初始化方法为反射class调用newInstance方法,详见 http://www ...
- Spring-Boot基于配置按条件装Bean
背景 同一个接口有多种实现,项目启动时按某种规则来选择性的启用其中一种实现,再具体一点,比如Controller初始化的时候,根据配置文件的指定的实现类前缀,来记载具体Service,不同Servic ...
- SpringBoot 配置 @PropertySource、@ImportResource、@Bean
一.@PropertySource @PropertySource:加载指定的配置文件 @PropertySource(value = {"classpath:person.properti ...
- SpringBoot学习之@Configuration注解和@Bean注解
@Configuration 1.@Configuration注解底层是含有@Component ,所以@Configuration 具有和 @Component 的作用. 2.@Configurat ...
随机推荐
- C#的函数使用 和参数修饰符 out ref params
// 函数和方法 // 函数好比对象的动作行为 在定义函数的时候,职责(作用/功能)越单一越好 满足高内聚 低耦合的开发思路 // 变量的命名规则 小驼峰 // 函数的命名规则 大驼峰 动词开头 // ...
- 将Vscode添加右键打开文件夹功能
1. wan + r 输入 regedit 打开注册表 注册表编辑 2. 找到 HKEY_CLASSES_ROOT\*\shell分支 3. 在shell下新建"VisualCode&quo ...
- 2. 说一下vue2和vue3的区别 ?
1. vue3 使用 proxy 替换Object.defineProperty 实现数据响应式 ,所以vue3 的性能得到了提升 : 2. vue3 使用组合式 API 替代了 vue2 中的选项式 ...
- 安装完Oracle数据库后需要调整的参数
关闭审计 alter system set audit_trail = none scope=spfile; 180天密码过期 alter profile default limit PASSWORD ...
- 华为云-容器引擎CCE-部署Nginx应用
环境准备 注册华为云账号 复制下面地址到浏览器地址栏(https://reg.huaweicloud.com/registerui/cn/register.html?fromacct=c76cea9f ...
- 在 Kubernetes 中运行 Locust 与 Selenium:安装 Chrome 和 ChromeDriver
在现代软件开发中,性能和用户体验是至关重要的,而负载测试和自动化测试可以帮助我们实现这一目标.在本文中,我们将讨论如何在 Kubernetes 环境中运行 Locust 和 Selenium,并详细介 ...
- ABC370 E - Avoid K Partition
ABC370 E - Avoid K Partition 求一个序列的合法划分方案数.一种划分合法当且仅当没有一个子串的和是 \(k\). 由于是否存在子串和为 \(k\) 很重要,因此考虑将它加入状 ...
- img标签src引用网络图片,响应403的解决方法
在html页面加入<meta name="referrer" content="no-referrer">标签,就可以解决页面加载网络图片的问题, ...
- 摒弃传统setInterval, 自己封装一个
传统的setInterval在某种情况下会导致内存泄漏,每次调用都会占用一部分内存空间,既然threejs的更新都是基于# requestAnimationFrame的循环调用,那么我们就可以利用这个 ...
- JAVA 传输post传输长字符、数据编码解码 反序列化字符串
JAVA 传输post传输长字符.数据编码解码 1.前段传输 这是传输的数组对象 2.后端接收格式已解码 JS代码: $.ajax({ url:prefix+"/importModelTre ...