让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean
让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean
问题描述
目前我工作环境下,后端主要的框架是Spring Boot,目前面临的问题也是在Spring Boot中出现的.
具体情况是这样的,期望是搭建一个公用的框架,适用于多种业务场景的,集成好如Redis,日志管理,定时任务管理等一系列配置即用的框架,但是在集成好Activiti框架后我发现有的项目并不需要使用Activiti框架,但是由于我使用的Maven依赖如下:
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-actuator</artifactId>
<version>${activiti.version}</version>
</dependency>
可以看到是使用了starter系列的依赖,所以Spring Boot会在启动时默认初始化Activiti相关的JAVA Bean,这个时候会出现以下问题:
- 初始化这些我用不到的bean可能需要一些配置文件等资源,而这个框架因为这个项目没有使用,所以没有从而导致的启动报错[在我目前的场景下是没有Activiti的流程图文件]
- 即便初始化这些JAVA Bean没有问题,但是某些依赖可能会改变我数据库的表结构[在我这个场景下是会在我的数据库中添加25个以
ACT_开头的表] - 当部署的服务器资源比较紧张的时候,这些多余的JAVA Bean会额外占用本来就不多的内存资源
由于我自己对Activiti的方法还做了一些封装,相当于提供了一个Service层的接口来使得代码编写更加简单,这部分代码我并不希望从脚手架中删除掉,比较部分项目还是需要使用的,所以我现在需要实现的就是在Spring Boot项目启动的时候,让它根据我在application.yml文件中的配置来确定需要初始化哪些JAVA Bean.
实现思路
这里我有三个思路:
- 思路一:直接移除相关依赖
- 思路二:增加一个自定义的注解,当满足我的配置的时候我再初始化我的Bean否则不初始化这些Bean
- 思路三:把我对Activiti的包装部分集合成一个项目,然后提供一个类似于activiti-spring-boot-starter的start类型的包给到我的具体项目中去
思路一 [不符合要求]
之前也提到了,由于我自己对Activiti的方法还做了一些封装,如果移除了Activiti的Maven依赖,会直接导致我封装的代码报错,所以这种方式并不能满足我的要求,不再赘述
思路二[满足要求]
这里我参照了简书作者@数齐 的名为SpringBoot基础教程(十八)——自定义条件注解的博文,成功实现了根据我的配置加载Bean的功能,核心代码如下:
- 注解
import com.hykj.activiti.annotation.impl.ActivitiConditionImpl;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
@Conditional(ActivitiConditionImpl.class)
public @interface ActivitiCondition {
}
- 注解的实现
import com.google.common.base.Strings;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 是否需要activiti的注解<br/>
* 如果需要activiti的话,那么在application加入sys.need-activiti=true <br/>
* 其他情况不再初始化activiti的相关bean
*
* @author weizj
*/
public class ActivitiConditionImpl implements Condition {
/** 启动的配置值 */
private static String ENABLE = "true";
/** 配置的属性名 */
private static String CONFIG_PROPERTY_NAME = "sys.need-activiti";
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String propertyValue = conditionContext.getEnvironment().getProperty(CONFIG_PROPERTY_NAME);
return !Strings.isNullOrEmpty(propertyValue) && propertyValue.equalsIgnoreCase(ENABLE);
}
}
- 注解的应用
import com.hykj.activiti.annotation.ActivitiCondition;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
/**
* Activiti流程引擎的配置
*/
@Configuration
@ActivitiCondition
public class ActivitiConfig {
@Autowired
public ActivitiConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
private DataSource dataSource;
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SpringProcessEngineConfiguration springProcessEngineConfiguration() {
System.out.println("=======================");
SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
//配置项内容设置
configuration
//设置数据库的类型
.setDatabaseType("mysql")
//使用springboot自带的数据源
.setDataSource(dataSource)
//设置字段更新类型
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
//
.setJobExecutorActivate(true)
//设置历史记录级别
.setHistoryLevel(HistoryLevel.FULL)
//设置标签字体
.setLabelFontName("宋体")
//设置注解字体
.setAnnotationFontName("宋体")
//设置图形字体
.setActivityFontName("宋体")
;
configuration.setTransactionManager(transactionManager());
return configuration;
}
}
- 配置文件
sys:
need-activiti: 11
到这里为止,如果配置文件中sys.need-activiti的值为true的时候Spring Boot启动的时候才会加载我配置的ActivitiConfig类中的Bean,但是这并不能让Spring Boot在启动的时候不初始化Activiti相关的如:RuntimeService/IdentityService/TaskService/RepositoryService/HistoryService等由activiti-spring-boot-starter-basic依赖自动装配的Bean.
正当我以为这条路走不通的时候我看到了@SpringBootApplication注解中包含exclude属性,我之前用它排除了org.activiti.spring.boot.SecurityAutoConfiguration.class类来避免Activiti的安全认证和Spring Secrity以及Apache Shrio之间的冲突问题.在当前的情况下,我已经在项目启动的时候完成了我自己类的去除,只要再去掉由于activiti-spring-boot-starter-basic包存在所初始化的类大概就可以了,于是我的@SpringBootApplication从这样:
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, org.activiti.spring.boot.SecurityAutoConfiguration.class})
变成了这样:
@SpringBootApplication(exclude = {
SecurityAutoConfiguration.class,
//不论是否使用activiti都要关闭这个类
org.activiti.spring.boot.SecurityAutoConfiguration.class,
//不使用activiti关闭的类开始
org.activiti.spring.boot.EndpointAutoConfiguration.class,
org.activiti.spring.boot.JpaProcessEngineAutoConfiguration.class,
org.activiti.spring.boot.DataSourceProcessEngineAutoConfiguration.class,
org.activiti.spring.boot.RestApiAutoConfiguration.class
//不使用activiti关闭的类结束
})
这时启动我的项目,发现数据库中并没有生成ACT_开头的表,也就意味着我已经完全去除了activiti-spring-boot-starter-basic所带来的JAVA Bean.
至此问题圆满解决.
思路三[未试验]
目前来说思路二是把和Activiti相关的初始化,封装的方法单独抽成一个JAR依赖,在需要它的时候引入这个依赖,这样Spring Boot在启动的时候是觉得不会装配多余的JAVA Bean,之前面临的问题也能得到有效的解决.因为时间问题,我没有试验这个思路,希望以后有机会填坑.
让Spring Boot项目启动时可以根据自定义配置决定初始化哪些Bean的更多相关文章
- spring boot 项目启动无任何反应
遇到的问题 spring boot项目启动后无任何报错,ps有进程,nohub无日志 定位 更换jar包,问题依然存在,将jar包放到其他服务器,运行正常,排除打包问题 同服务器其他系统运行正常,但停 ...
- Spring Boot 2 启动时加载properties文件
每个项目从开发到测试再到上线所需要的各种环境是不同的,这就需要维护相应的配置文件,比如properties或yml文件.有了配置文件后就要考虑如何与应用进行集成. 对于云环境来讲,项目发布需要打成镜像 ...
- Spring Boot 设置启动时banner
Spring Boot项目再启动的时候默认会在控制台输出一个字符banner图案,如下图: 我们可以通过下面的方法关闭启动时显示字符banner图案: 关闭banner方法一: public stat ...
- 1.Spring项目启动时,加载相关初始化配置
Spring项目启动时,会加载一些常用的配置: 1.加载spring上下文 SpringApplicationContextUtils.initApplicationContext(event.get ...
- spring boot项目启动报DataSource错误
初建一个简单的spring boot 项目,启动后会报错. Exception encountered during context initialization - cancelling refre ...
- 创建spring boot项目启动报错遇到的问题
1.Spring boot,Mybatis 启动报错 Failed to auto-configure a DataSource *************************** APPLICA ...
- Spring Boot 在启动时进行配置文件加解密
Spring Boot Application 事件和监听器 寻找到application.yml的读取的操作. 从spring.factories 中查看到 # Application Listen ...
- spring boot 项目搭建时,各个依赖的作用
项目搭建页面 https://start.spring.io/ 各个依赖的作用 List of dependencies for Spring Boot 2.1.5.RELEASE Core DevT ...
- Spring Boot 项目在 IntelliJ IDEA 中配置 DevTools 实现热部署(macOS 系统)
要配置的内容: 1.Preference -> Build, Execution, Deployment -> Complier -> Build project automatic ...
随机推荐
- Maven打包后的文件存在中文乱码
发现打包的js文件虽然是UTF-8格式的编码,但是有中文有乱码 可设置jvm的编码,两种方法: 在系统的环境变量中添加一个变量,名为: JAVA_TOOL_OPTIONS, 值为:-Dfile.enc ...
- vue-cli 报Module build failed: Error: No parser and no file path given, couldn't infer a parser.错的解决方法
出错提示如下: ERROR Failed to compile with errors :: error in ./src/App.vue Module build failed: Error: No ...
- 2019/4/17 Linux学习
一.Linux的文件系统 其中/prov./srv./sys 文件为文件系统,技术不过硬不要去修改:二.关于Xshell.Xft1.服务器的端口可有65535个可设置,开的越多安全性越差:2.远程登录 ...
- 微信小程序问题---数据传输长度为 1275870 已经超过最大长度 1048576
开发微信小程序时,遇到数据传输长度为 1095538 已经超过最大长度 1048576的问题. 这是setData时操作数据过大导致,一般出现在请求返回数据过大,我们又将这个数据一次性用setData ...
- CAS 无锁队列
队列是常用的数据结构,采用的FIFO(first in firstout)原则,新元素(等待进入队列的元素)总是被插入到尾部,而读取的时候总是从头部开始读取.在计算中队列一般用来做排队(如线程池的等待 ...
- 微信小程序:request合法域名检验出错,https://apis.map.qq.com 不在以下 request 合法域名列表中
设置域名 登录微信小程序后台, 设置→开发设置→服务器设置 必须设置域名,微信小程序才能进行网络通讯,不然会报错 如果没有设置合法域名,在开发阶段是可以不设置合法域名的 详情 -项目设置 好了,完美解 ...
- CentOS7下Mysql 5.6.30安装与配置
环境:centos 7 x64 先下载mysql安装包 打开 http://dev.mysql.com/downloads/mysql/ 选择 linux - Generic 再选择 下载完毕后,得 ...
- 自制EF(iShare Demo版)
由于公司使用的所有技术都比较倾向于使用原生,不怎么借用其他第三方框架(无论是前端布局,样式,到后台的框架).公司也算比较小型的没有太大的项目 可以让我们进行团队合作项目,几乎是一人接手一个项目.然后自 ...
- SpringMVC中注解@RequestBody和@ResponseBody的使用区别
首先上源码 在面试时经常会问到我们如何使用SpringMVC将Http请求转换为java对象,或者又是问如何将结果转换为java的呢? SpringMVC在接收到请求之后HandlerMapping像 ...
- python_1_基础知识
数据类型: 整数 浮点数 字符串 布尔值:True/False 空值:None 变量 常量 int(整型):在Python3里不再有long类型了,全都是int -2**63-2**63-1即-922 ...