二、容器功能
1、组件添加等注解
上面我们学习到了SpringBoot的一些优势和特点,下面我们继续学习上面我挖的一些坑。
@Configuration
首先是这个基本注解类,这个类非常好理解,就是它的翻译——配置。这个注解就是用于标记配置类来使用的,如果我们想设置哪个类为配置类,只需要在其上方添加上如下注解:
@Configuration(proxyBeanMethods = false)
如果我们点击进入这个Configuration
查看这个注解的源码,我们就可以发现它是由几个注解联合实现的:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
首先@Target这个很简单,如果我们学过Java的基础知识,就会有了解,这是Java自带的注解,用于标记自定义注解的作用范围,这里的TYPE
是代表了作用在类上。
然后是@Retention注解,这个注解也很简单,表明了注解生效的时间段,这里是运行时作用。
然后是@Documented注解,这是一个元注解,和Target一样,是底层封装好的注解,用于生成文档时候的注解显示格式。
接着是@Component这个注解我们很熟悉了,在SpringMVC中经常见到,把组件放入容器中,便于管理。
可以看到这个@Configuration
注解是几个常见注解的组合。细心的小伙伴可能会发现,这里还有一个属性值不一样proxyBeanMethods
。在这里我们把它设置为了false
。
这个属性如果我翻译过来就是代理Bean方法,我们知道配置类中如果试用了@Bean
进行标注注册,默认都是单实例的,这里要给不太了解设计模式的小伙伴说一下,简单来讲,单实例就是常说的单例模式,每个Bean被创建后,在整个生命周期内,也就是这个Bean在被销毁前,它都是独一无二的,我们不能对这个Bean标记的方法重复创建第二个Bean,用代码来讲如下:
import com.zxy.boot.Pojo.Car;
import com.zxy.boot.Pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@Bean
public User user(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Car组件
zhangsan.setMycar(tomcatCar());
return zhangsan;
}
@Bean
public Car tomcatCar(){
return new Car("Porsche");
}
}
//Car类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
private String brand;
}
//User类
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private int age;
private Car mycar;
public User(String username, int age){
this.username = username;
this.age = age;
}
}
我们看这样一个配置类,这里面设计了两个Bean,其中我们的User组件依赖于下面的Car组件,当我们调用user组件的时候,会去使用第二个组件,这时如果我们的第二个组件不是单独唯一的,就会使得我们获取到的结果不唯一,此时两次创建的Car组件是不同的,这时候就会导致问题,如果我们上面的注解设置了true
属性,SpringBoot就会是开启单例模式控制,生成的组件都是唯一的,就能够保证组件依赖的安全性。
如果我们设置了false
值,就会关闭单例模式,每当调用Car模块都会创建一个新的实例,这样每次生成的都不一样。
在SpringBoot的官方文档中,给这两种情况命名为Full模式和Lite模式。
Full模式就是值为true
的情况,这种模式适合组件之间存在互相依赖调用关系的情况。
Lite模式就是值为false
的情况,这种模式适合组件之间没有依赖关系,想要加快启动速度的情况。
@Bean、@Component、@Controller、@Service、@Repository
这几个注解MVC讲的很熟悉了,就不再多说了
@ComponentScan、@Import
这两个注解都顾名思义,都是导入xxx模块,第一个是熟悉的包扫描,可以对指定目录下的类进行扫描,注册类种的Bean组件。
Import主要是针对自定义的一些模块导入,比如我在这个配置文件中需要某个配置模块或自定义模块,就可以通过Import进行导入。
上面的注解都是一般情况,下面的条件装备才是重点。
@Conditional
条件装配:当满足某个条件时,才会进行组件注入。
我们可以看到这个@Conditional只是一个基础,它有特别多的注解实现,对这个注解进行了扩展,它们的大致意思其实都很好理解,比如
ConditionalOnMissingBean
这个就是代表了如果缺失了我指定的一个Bean组件,我就将我配置的组件注入。其他的类实现大家可以自己推理一下,其实不难。
2、原生配置文件
@ImportResource
我们在SpringMVC中我们经常要用xml文件进行配置,如果你是想把原来MVC中的一些配置直接挪用到新的SpringBoot项目中,这个注解就可以帮你导入配置信息,它会自动读取你传递的xml文件中的配置组件,并在你配置的配置类符合注入条件的时候进行系统统一注入。
3、配置绑定
@Component + @ConfigurationProperties
通过这两个注解注释的组件类,会通过识别系统配置文件application.properties\application.yml
中的指定前缀(需要在ConfigurationProperties中配置prefix属性值)的值赋给设置的组件:
/**
* 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
*/
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
@EnableConfigurationProperties + @ConfigurationProperties
这两个注解同样可以实现上述操作:
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
将@EnableConfigurationProperties
注解放在配置文件类上,另一个放在配置组件上,即可实现与上述配置相同的结果。