SpringBoot2 底层注解
@Configuration注解:
Spring中:
bean 包放数据类,比如 User、Pet。
config 包放配置类,比如 MyConfig,用来告诉 Spring 创建哪些对象。
@Configuration注解:标在类上,表示这个类是一个“配置类”,即专门用来告诉 Spring 应该创建哪些对象、怎么创建对象、怎么配置项目行为的类。
@Bean注解:标在方法上,表示这个方法返回的对象要放进 Spring 容器。配置类本身也在Spring容器里面。
如:
在Bean包里新建:
User类:
package com.inex.Bean;
public class User {
private String name;
private Integer age;
public User(){
}
public User(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public Integer getAge(){
return age;
}
}
Pet类:
package com.inex.Bean;
public class Pet {
private String name;
private Integer age;
public Pet(){}
public Pet(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public Integer getAge(){
return age;
}
}
然后在config包新建Myconfig类:
package com.inex.config;
import com.inex.Bean.Pet;
import com.inex.Bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration //告诉SpringBoot这是一个配置类 == 一个配置文件
class MyConfig {
@Bean //给容器添加组件,以方法名作为组件id,返回类型就是组件类型,返回的值就是组件在容器中的实例
public User user01(){
return new User("inex",18);
}
@Bean("Jerry") //也可以这样自定义id
public Pet miaomiao(){
return new Pet("Tom",3);
}
}
通过如下代码得知,我们从Bean容器里通过id和类型拿到的一直都是同一个对象
package com.inex;
import com.inex.Bean.Pet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class MainApplication {
public static void main (String[] args){
// 1、返回我们的IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
// 2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
// 3. 从容器中获取组件
Pet tom01 = run.getBean("Jerry", Pet.class);
Pet tom02 = run.getBean("Jerry", Pet.class);
System.out.println("组件:" + (tom01 == tom02));
}
}
默认情况下@Configuration(proxyBeanMethods = true),也叫 Full 模式。这种情况下,Spring 会给配置类创建一个代理对象。如果你调用一个 @Bean 方法:
zhangsan.setPet(miaomiao());
或者在配置类外:
Pet pet01 = Myconfig.miaomiao();
Spring 会拦截这个调用,不是真的重新执行 miaomiao(),而是从容器里拿已经创建好的那个 Pet 对象。
可以设置@Configuration(proxyBeanMethods = false),也叫 Lite 模式。这种情况下,Spring 不会代理这些 @Bean 方法。
这时:
zhangsan.setPet(miaomiao());
就是一次普通 Java 方法调用,会真的执行:
return new Pet("Tom",3);
也就是说,会新创建一个 Pet 对象。
同时,Spring 容器自己也会注册一个叫 "Jerry" 的 Pet 对象。
proxyBeanMethods = true 适合:配置类里的 Bean 方法之间有互相调用、互相依赖。
proxyBeanMethods = false 适合:配置类里的 Bean 方法互相独立,不互相调用。这样启动会更快速
@Import注解:
使用格式:
@Import({User.class, DBHelper.class})
它的作用是:把指定的类导入到 Spring 容器中,让 Spring 自动创建这些类的对象。对象名默认就是类的全限定名
一般写在配置类里,需要注意的是,如果导入的是这个配置类本身@Bean 方法创建的,那还是会出现两个不同的对象
例:
@Configuration
@Import(User.class)
public class MyConfig {
@Bean
public User user01() {
return new User("zhangsan", 18);
}
}
验证代码:
String[] beanNamesForType = run.getBeanNamesForType(User.class);
System.out.println("======");
for (String s : beanNamesForType) {
System.out.println(s);
}
@Conditional注解:
作用:满足某种条件才把组件注册到 Spring 容器里,不满足条件就当这段配置不存在。有很多下属注解,比如@ConditionalOnBean就是要在容器里有符合某条件时才注入该注解下的内容
例如:
@Bean
@ConditionalOnBean(name = "tomcatPet")
public User user01() {
return new User("zhangsan", 18);
}
就是要在容器里有叫tomcatPet的对象时才继续注入该注解下的内容
@ImportResource注解:
把传统 Spring 的 XML 配置文件导入到 Spring 容器中。
主要用于:有 beans.xml 这种配置文件,现在项目换成 Spring Boot 了,但还想继续使用 XML 里的 Bean 配置,就可以用这个注解,通过路径将XML的Bean配置写进容器,一般写在主类和配置类里面
例:
@ImportResource("classpath:beans.xml")
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run =
SpringApplication.run(MainApplication.class, args);
User user = run.getBean("haha", User.class);
System.out.println(user);
}
}
ps:在 Spring Boot 项目里,src/main/resources 下面的文件,运行时会进入 classpath。
@ConfigurationProperties、@Component、@EnableConfigurationProperties注解:
@ConfigurationProperties:
把配置文件中的一组属性,绑定到一个 Java 类上。
@Component:
把这个类注册到 Spring 容器中。
@EnableConfigurationProperties:
开启某个配置属性类(即使ConfigurationProperties可用),并把它注册到容器中。
由于只有在容器中的类才有@ConfigurationProperties功能,所以要么先通过@Component将类注入到容器中,要么通过
@EnableConfigurationProperties解决。
例:
配置文件application.properties有:
mycar.brand=BYD
mycar.price=100000
然后再在Bean下有.java文件:
@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;
}
}
就会自动把注册到容器里的Car类对象的brand和price设置成对应值。
这里:
@ConfigurationProperties(prefix = "mycar")
意思是:读取所有以 mycar 开头的配置。
或者写:
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
// getter / setter
}
然后在启动类上写:
@SpringBootApplication
@EnableConfigurationProperties(Car.class)
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
也可