说到Spring Boot应用,不得不先聊聊它的那些注解们。让我们先从springboot的启动类开始,看看注解们到底都默默为我们做了哪些事情。
Spring Boot启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication是一个组合注解,拥有三个注解的功能 @ComponentScan、@EnableAutoConfiguration、@SpringBootConfiguration,下面来分别介绍一下这三个注解各自的功能。
@SpringBootConfiguration
@EnableAutoConfiguration(exclude = { cn.xiaohuanxiong.service.S3MapperAutoConfiguration.class })
@ComponentScan("cn.xiaohuanxiong")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@ComponentScan 自动扫描组件
@ComponentScan("cn.xiaohuanxiong")
该注解可以扫描包下所有@component注解标记或拓展@component注解标记的Bean并注册到spring容器中。与在applicationContext.xml中指定<context:component-scan base-package="cn.xiaohuanxiong" />
,作用是相同的,实现项目内Bean的初始化和注册。@Service、@Repository、@Configuartion等注解都是@Component的派生注解,他们的作用都是spring扫描类时会对加上这些注解的类自动装配到Spring容器中进行管理。只是注解分多个名称来标注,阅读代码时更好的理解代码的作用,与xml中配置<bean id="" class=""/>作用相同
@EnableAutoConfiguration 自动配置机制
Spring Boot 最核心的注解,可以根据类路径下 jar 包和配置动态加载配置和注入bean,扫描SpringBoot启动类所在包及子包的组件类和自动配置类(其中自动配置类会在META-INF/spring.factories
文件中指定),将其初始化注入到Spring容器中。
spring.factories
文件 ,会配置接口的实现类名称,可以同时指定多个实现类,一般放在模块的resources/META-INF
目录下。例如spring-core包里定义了SpringFactoriesLoader类,会检索META-INF/spring.factories
文件,通过Properties解析类名并实例化。Factories机制可以减少配置,在jar包中引入即可实现功能。spring.factories功能实现是Java的SPI机制很好的运用和体现。
这里顺便介绍一下Java的SPI机制,SPI
全称为Service Provider Interface
,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。基于接口编程并结合策略模式和配置文件的组合来实现动态加载的一种机制。面向对象的设计里,推荐模块之间基于接口编程,遵循可插拔的原则,模块之前不对实现类硬编码。SPI就提供这种服务发现机制,将装配的控制权移动到程序之外,实现解耦。使用场景例如JDBC加载不同类型数据库驱动,日志接口实现类加载
Spring Mvc应用在启动WebMvc时需要在xml上添加很多配置,但Spring Boot的应用,只要引入starter-web包,在程序启动时会将spring-boot-autoconfigure-2.1.4.RELEASE.jar
包下的META-INF\spring.factories
配置文件org.springframework.boot.autoconfigure.EnableAutoConfiguration
为key的类加载到IOC容器中,其中就有启动WebMvc需要配置的自动配置类WebMvcAutoConfiguration,这个类初始化就会帮我们配置好webMVC需要的配置。又比如启动springboot web时不配置server.port,默认的端口号为8080,这也是通过自动配置类初始化的
@SpringBootConfiguration
@SpringBootConfiguration注解是@Configuration的派生注解,表示当前类是一个可以被组件扫描器扫描的配置类。@SpringBootConfiguration是被Spring Boot进行了重新封装命名,只是用来修饰是 Spring Boot 配置而已,或者可利于 Spring Boot 后续的扩展。而@Configuration注解是Spring 3.0 添加的一个注解,用来代替 applicationContext.xml 配置文件,通过xml配置文件所做的事情,现在都可以通过这个注解所在类进行注册。
另外与配置相关的其他注解还有@Bean、@ImportResource、@Import。
@Bean注解
用于代替xml中的<Bean>配置,在spring容器中注入类,通过spring容器来管理类,这样在程序中就可以直接使用这个类对象,通过@Autowired可以自动写入set/get方法,代替的xml配置如下:
<!-- id在spring容器中唯一, -->
<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" lazy-init="true">
<!-- constructor-arg表示构造方法注入,name为类的构造方法的参数名称,value表示参数值 -->
<!-- <constructor-arg name="param_field" value = "param_value"></constructor-arg> -->
<!-- property表示属性注入,通过类的set方法注入属性值 -->
<property name="corePoolSize" value="20"/>
<property name="maxPoolSize" value="200"/>
<property name="queueCapacity" value="1000"/>
<property name="keepAliveSeconds" value="300"/>
</bean>
@Bean用于告诉所注解的方法,产生一个Bean对象,并将Bean对象交给Spring容器去管理,该方法只会被Spring调用一次。
@Slf4j
@Configuration
public class MySelfConfig {
@Bean("beanObject")
public String createBeanMethod() {
return "this will be a bean object";
}
}
@Service
public class OtherService {
@Resource
private String beanObject;
public void test() {
System.out.println(beanObject);
}
}
因为交给Spring容器管理,所以可以通过@Resource直接使用beanObject对象,其中MySelfConfig可以是@Component或者派生注解修饰的类。
@ImportResource注解
通过这个注解可以引入外部xml配置文件,有些老的配置文件无法通过@Configuration方式配置的,会使用@ImportResource来配置。使用方式如@ImportResource("classpath:abcxml.xml")
。同xml中 <import resource="abcxml" />
作用相同。
@Import注解
用来引入额外的一个或者多个 @Configuration 修饰的配置文件类,用来整合所有@Configuration注解中定义的bean配置。功能类似于将多个xml文件导入到一个xml文件中。
注意与@ImportResource区分,@ImportResource是引入配置文件。在Spring4.2之前,Import注解只支持导入@Configuration注解修饰的配置类,从Spring4.2开始,Import注解支持导入普通的类。功能同xml中<import />
作用相同。支持三种类型的类注入:普通类、实现ImportSelector接口的类、实现ImportSelectorDefinitionRegistrar接口的类。
自动注入Bean的引用
通过@Component或派生注解修饰的自动注入bean里,如果需要引用其他bean,直接通过@Autowired 或 @Resource即可引用
@Component
public class MyBean {
@Autowired
private OtherBean othereBean;
}
在没有通过Spring容器管理的普通类中,如果有Spring容器实例化,且想要使用Spring容器中的对象,可以使用SpringBeanUtils工具来获取。
OtherBean otherBean = SpringBeanUtils.getBean(OtherBean.class);
好啦,注解们都介绍完了,是不是对Spring Boot启动时所做的事情有了更多的了解呢。
网友评论