SpringBoot应用程序的关闭目前总结起来有4种方式:
- Rest接口:使用spring-boot-starter-actuator模块里的ShutdownEndpoint
- SpringApplication的exit静态方法:直接调用该静态方法即可
- JMX:使用SpringBoot内部提供的MXBean
- 使用第三方进程管理工具
分享技术和生活
SpringBoot应用程序的关闭目前总结起来有4种方式:
Spring内置了一些很有用的BeanPostProcessor接口实现类。比如有AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、EventListenerMethodProcessor等。这些Processor会处理各自的场景。
正是有了这些processor,把bean的构造过程中的一部分功能分配给了这些processor处理,减轻了BeanFactory的负担。
而且添加一些新的功能也很方便。比如Spring Scheduling模块,只需要添加个@EnableScheduling注解,然后加个@Scheduled注解修饰的方法即可,这个Processor内部会自行处理。
Spring内部提供了一个BeanPostProcessor接口,这个接口的作用在于对于新构造的实例可以做一些自定义的修改。比如如何构造、属性值的修改、构造器的选择等等。
只要我们实现了这个接口,便可以对构造的bean进行自定义的修改。
对Spring类注册功能做个笔记,包括内置的一些扫描器以及这些扫描器的用途和注意点;还有bean注册相关的接口介绍;最后就是这些扫描器在SpringBoot上的使用。
在我们刚开始接触Spring的时候,要定义bean的话需要在xml中编写,比如:
1 | <bean id="myBean" class="your.pkg.YourClass"/> |
后来发现如果bean比较多,会需要写很多的bean标签,太麻烦了。于是出现了一个component-scan注解。这个注解直接指定包名就可以,它会去扫描这个包下所有的class,然后判断是否解析:
1 | <context:component-scan base-package="your.pkg"/> |
再后来,由于注解Annotation的流行,出现了@ComponentScan注解,作用跟component-scan标签一样,跟@Configuration注解配合使用:
1 | @ComponentScan(basePackages = {"your.pkg", "other.pkg"}) |
不论是component-scan标签,还是@ComponentScan注解。它们扫描或解析的bean只能是Spring内部所定义的,比如@Component、@Service、@Controller或@Repository。如果有一些自定义的注解,比如@Consumer、这个注解修饰的类是不会被扫描到的。这个时候我们就得自定义扫描器完成这个操作。
SpringBoot把配置文件的加载封装成了PropertySourceLoader接口,该接口的定义如下:
1 | public interface PropertySourceLoader { |
PropertySource是Spring对name/value键值对的封装接口。该定义了getSource()方法,这个方法会返回得到属性源的源头。比如MapPropertySource的源头就是一个Map,PropertiesPropertySource的源头就是一个Properties。
PropertySource目前的实现类有不少,比如上面提到的MapPropertySource和PropertiesPropertySource,还有RandomValuePropertySource(source是Random)、SimpleCommandLinePropertySource(source是CommandLineArgs,命令行参数)、ServletConfigPropertySource(source是ServletConfig)等等。
PropertySourceLoader接口目前有两个实现类:PropertiesPropertySourceLoader和YamlPropertySourceLoader。
PropertiesPropertySourceLoader支持从xml或properties格式的文件中加载数据。
YamlPropertySourceLoader支持从yml或者yaml格式的文件中加载数据。
在之前的一些文章中,我们提到过从spring.factories中找出key为XXX的类。比如@EnableAutoConfiguration注解对应的EnableAutoConfigurationImportSelector中的selectImport方法会在spring.factories文件中找出key为EnableAutoConfiguration对应的值。这些类都是自动化配置类:
// 这个spring.factories文件在spring-boot-autoconfigure模块的 META-INF/spring.factories中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
......
之前写过一篇SpringData ES 关于字段名和索引中的列名字不一致导致的查询问题,顺便深入学习下Spring Data Elasticsearch。
Spring Data Elasticsearch是Spring Data针对Elasticsearch的实现。
它跟Spring Data一样,提供了Repository接口,我们只需要定义一个新的接口并继承这个Repository接口,然后就可以注入这个新的接口使用了。
定义接口:
1 | @Repository |
注入接口进行使用:
1 | @Autowired |
SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包。在pom文件里加入这个插件即可:
1 | <build> |
打包完生成的executable-jar-1.0-SNAPSHOT.jar内部的结构如下:
├── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── spring.study
│ └── executable-jar
│ ├── pom.properties
│ └── pom.xml
├── lib
│ ├── aopalliance-1.0.jar
│ ├── classmate-1.1.0.jar
│ ├── spring-boot-1.3.5.RELEASE.jar
│ ├── spring-boot-autoconfigure-1.3.5.RELEASE.jar
│ ├── ...
├── org
│ └── springframework
│ └── boot
│ └── loader
│ ├── ExecutableArchiveLauncher$1.class
│ ├── ...
└── spring
└── study
└── executablejar
└── ExecutableJarApplication.class
然后可以直接执行jar包就能启动程序了:
1 | java -jar executable-jar-1.0-SNAPSHOT.jar |
最近工作中使用了Spring Data Elasticsearch。发生它存在一个问题:
Document对应的POJO的属性跟es里面文档的字段名字不一样,这样Repository里面编写自定义的查询方法就会查询不出结果。
比如有个Person类,它有2个属性goodFace和goodAt。这2个属性在es的索引里对应的字段表为good_face和good_at:
1 | @Document(replicas = 1, shards = 1, type = "person", indexName = "person") |
Repository中的自定义查询:
1 | @Repository |
方法findByGoodFace是查询不出结果的,而findByName是ok的。
为什么findByGoodFace不行而findByName可以呢,来探究一下。