从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的活动范围的更多相关文章

  1. 尚硅谷springboot学习10-@PropertySource,@ImportResource,@Bean

    @PropertySource 使用指定的属性文件而不一定是application.xxx 同样可以注入相关内容 @ImportResource 导入Spring的配置文件,让配置文件里面的内容生效: ...

  2. springboot根据不同的条件创建bean,动态创建bean,@Conditional注解使用

    这个需求应该也比较常见,在不同的条件下创建不同的bean,具体场景很多,能看到这篇的肯定懂我的意思. 倘若不了解spring4.X新加入的@Conditional注解的话,要实现不同条件创建不同的be ...

  3. SpringBoot配置——@PropertySource、@ImportResource、@Bean

    @PropertySource:加载指定的配置文件 package com.hoje.springboot.bean; import org.springframework.beans.factory ...

  4. SpringBoot框架(4)-- 类装配及Bean装配监听器

    1.普通方式装配类对象   (1)添加带有@Bean注解的方法  User.java(带@Component注解) package com.demo.boot.bootenable.beanDemo1 ...

  5. SpringBoot拦截器中无法注入bean的解决方法

    SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ...

  6. springboot available: expected at least 1 bean which qualifies as autowire candidate奇葩问题

    Exception encountered during context initialization - cancelling refresh attempt: org.springframewor ...

  7. springboot中velocity tool中注入bean

    在使用springboo的时候,遇到一个问题,想在tool类中注入一个bean,一直失败,翻了下源码,是因为工具类的初始化方法为反射class调用newInstance方法,详见 http://www ...

  8. Spring-Boot基于配置按条件装Bean

    背景 同一个接口有多种实现,项目启动时按某种规则来选择性的启用其中一种实现,再具体一点,比如Controller初始化的时候,根据配置文件的指定的实现类前缀,来记载具体Service,不同Servic ...

  9. SpringBoot 配置 @PropertySource、@ImportResource、@Bean

    一.@PropertySource @PropertySource:加载指定的配置文件 @PropertySource(value = {"classpath:person.properti ...

  10. SpringBoot学习之@Configuration注解和@Bean注解

    @Configuration 1.@Configuration注解底层是含有@Component ,所以@Configuration 具有和 @Component 的作用. 2.@Configurat ...

随机推荐

  1. electron 菜单选项 - 隐藏,设置菜单

    隐藏菜单 const { app, Menu, session } = require('electron'); /*隐藏electron的菜单栏*/ Menu.setApplicationMenu( ...

  2. Required request parameter ‘xxx‘ for method parameter type xxxx is not present 解决方式

    我在controller层传实体参数时加了@RequestParam,结果报Required request parameter 'pointlist' for method parameter ty ...

  3. 快来考试拿证书!KubeSphere 个人技能专业考试认证上线啦!

    以容器技术和容器编排为基础的云原生应用,被越来越多的企业用户接受和使用,并且在生产环境中使用容器技术的比例逐年增加.Kubernetes 无疑已经成为容器编排的事实基础,而依托于 Kubernetes ...

  4. appium环境搭建及命令行启动sdk模拟器-附踩坑以及解决过程

    安装教程这里就不阐述了,网上一大堆教程,下载完成后安装然后配置对应的环境变量即可 android sdk及java home配置: path配置: %ANDROID_HOME%\platform-to ...

  5. activiti教程

    一.工作流介绍 1.1 概念 工作流(Workflow),就是通过计算机对业务流程自动化执行管理.它主要解决的是"使在多个参与者之间按照某种预定义的规则自动进行传递文档.信息或任务的过程,从 ...

  6. Saas多租户数据权限设计(参考RuoYi)

    导航 引子 场景梳理 基于角色的访问控制(RBAC) 多租户系统的权限设计 RuoYi系统的数据权限设计 最终设计方案 参考 本文首发<智客工坊-Saas多租户数据权限设计(参考RuoYi)&g ...

  7. Linux Ubuntu 安装Python独立的不同版本

    由于Ubuntu系统默认的Python版本基本为3.5.2,老掉牙的版本了,很多功能语法不可以使用,删除也并不好操作.所以不如新装一个最新的版本.速度快,操作简单,最重要的是使用只需要键入python ...

  8. BeautifulSoup优化测试报告

    一.是什么 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库. 中文官方文档:https://beautifulsoup.readthedocs.io/zh_C ...

  9. 关于C++当中的指针悬空问题

    一.哪里遇到了这个问题 在进行MNN机器学习框架的MFC应用开发的时候遇到了这个问题,在窗口控件代码段 "MNN_Inference_BarCode_MFCDlg.cpp" 当中需 ...

  10. 由C#委托回调想到的二三事

    写在前面: 之前的过开发程中,我愈发觉得面对复杂的界面要求,最好还是用UserControl将不同模块的界面设计单独封装,以应对客户频繁地需求更改.这样做能够在面对对不同的UI要求时,动态的加载预先设 ...