前言
本文主要讲诉@Configuration、@Import、@Conditional、@ImportResource、@ConfigurationProperties注解。
先将实体类给大家,方便下面测试:
get、set、构造器大家自己添加,这里我用的是ToString等注解(以后会出文章讲诉)所以没写这些,就不列出来了。
public class Pet { private String name; } ================================= public class User { private String name; private Integer age; private Pet pet; } ============================ public class Car { private String brand; private String price; }
一、@Configuration
1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的,所谓单实例跟我们在Spring中了解的bean创建对象的单实例是一样的,就是在调用getBean方法创建相同类型实例对象时,这些对象的地址相同(即无论创建多少对象,都是同一个对象)。多实例就是每次创建对象都重新创建一个不同地址的新对象。
2、配置类本身也是组件。
3、proxyBeanMethods:代理bean的方法。
Full模式(proxyBeanMethods = true)(保证每个@Bean方法被调用多少次返回的组件都是单实例的)(默认)
Lite模式(proxyBeanMethods = false)(每个@Bean方法被调用多少次返回的组件都是新创建的)
配置类:
@Configuration(proxyBeanMethods = true) //告诉SpringBoot这是一个配置类 == 配置文件 public class MyConfig { /** * Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象 * @return */ @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例 public User user01(){ User zhangsan = new User("zhangsan", 18,tomcatPet()); //user组件依赖了Pet组件 return zhangsan; } @Bean("tom") public Pet tomcatPet(){ return new Pet("tomcat"); } }
SpingBoot启动类
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.dragon.boot") 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("tom", Pet.class); Pet tom02 = run.getBean("tom", Pet.class); System.out.println("组件:"+(tom01 == tom02)); //4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892 MyConfig bean = run.getBean(MyConfig.class); System.out.println(bean); //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。 //保持组件单实例 User user = bean.user01(); User user1 = bean.user01(); System.out.println(user == user1); User user01 = run.getBean("user01", User.class); Pet tom = run.getBean("tom", Pet.class); System.out.println("用户的宠物:"+(user01.getPet() == tom)); } }
看运行结果分析:
- 组件:true
配置类中我用的Full模式:@Configuration(proxyBeanMethods = true) ,当然就是单实例模式,所有创建的对象都是同一个对象。 - com.dragon.boot.config.MyConfig$ $ SpringCGLIB$$0@283e8358
这个输出是我getBean获取的配置类组件,可以看出配置类本身也是组件。 - 用户的宠物:true
当我开启单实例模式时,就能够处理依赖关系,这里我创建的组件宠物==用户组件里的宠物,User zhangsan = new User("zhangsan", 18,tomcatPet());
。我创建的用户组件时就是调用的tomcatPet(),因为是单实例模式,所以我在创建用户调用创建的宠物和直接创建的宠物都是同一个对象。
启动类中我写了个查看容器里面的组件的方法,注释掉了,可以运行,在控制台Ctrl+F搜索查看注册的组件。
将proxyBeanMethods 属性改成false,运行结果就变成了false。
总结:
- 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
- 配置 类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式(默认)
二、@Import导入组件
@Bean、@Component、@Controller、@Service、@Repository,它们是Spring的基本标签,在Spring Boot中并未改变它们原来的功能。
@ComponentScan在Spring学习中大家一定接触了吧,就是开启组件扫描。
Import({User.class、DBHelper.class})会给容器中自动创建出User、DBHelper组件,默认组件的名字就是全类名。如果创建多个组件就在在大号内添加,用逗号隔开。
@Import({User.class,DBHelper.class}) @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件 public class MyConfig { //.... }
启动类:
//1、返回我们IOC容器 ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); //... //5、获取组件 String[] beanNamesForType = run.getBeanNamesForType(User.class); for (String s : beanNamesForType) { System.out.println(s); }
三、@Conditional条件装配
条件装配:满足Conditional指定的条件,则进行组件注入
这里用@ConditionalOnMissingBean举例说明:
- @ConditionalOnMissingBean(name = “tt”)
用在类上:没有tt名字的Bean时才会将类里所有配置注册成组件
用在方法上:没有tt名字的Bean时才会将改方法注册成组件
@Configuration(proxyBeanMethods = true) //告诉SpringBoot这是一个配置类 == 配置文件 @Import({User.class}) @ConditionalOnMissingBean(name = "tom") public class MyConfig { /** * Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象 * @return */ @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例 public User user01(){ User zhangsan = new User("zhangsan", 18,tomcatPet()); //user组件依赖了Pet组件 return zhangsan; } @Bean("tom") public Pet tomcatPet(){ return new Pet("tomcat"); } }
启动类:
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); //2、查看容器里面的组件 String[] names = run.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } boolean tom = run.containsBean("tom");//是否包含某个组件 System.out.println("容器中Tom组件:"+tom);//false boolean user01 = run.containsBean("user01"); System.out.println("容器中user01组件:"+user01);//true boolean tom22 = run.containsBean("tom22"); System.out.println("容器中tom22组件:"+tom22);//true
四、@ImportResource导入Spring配置文件
公司项目使用bean.xml文件生成配置bean,然而你为了省事,想继续复用bean.xml,@ImportResource粉墨登场。
bean.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <bean id="haha" class="com.dragon.boot.bean.User"> <property name="name" value="zhangsan"></property> <property name="age" value="18"></property> </bean> <bean id="hehe" class="com.atguigu.boot.bean.Pet"> <property name="name" value="tomcat"></property> </bean> </beans>
复用方法:
@ImportResource("classpath:bean.xml") public class MyConfig { //... }
启动类测试:
//1、返回我们IOC容器 ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); boolean haha = run.containsBean("haha"); boolean hehe = run.containsBean("hehe"); System.out.println("haha:"+haha);//true System.out.println("hehe:"+hehe);//true
返回true,说明注册成了组件。
五、@ConfigurationProperties配置绑定
使用Java读取到properties文件中的内容,并且把它封装到JavaBean中
传统方法:
public class getProperties { public static void main(String[] args) throws FileNotFoundException, IOException { Properties pps = new Properties(); pps.load(new FileInputStream("a.properties")); Enumeration enum1 = pps.propertyNames();//得到配置文件的名字 while(enum1.hasMoreElements()) { String strKey = (String) enum1.nextElement(); String strValue = pps.getProperty(strKey); System.out.println(strKey + "=" + strValue); //封装到JavaBean。 } } }
SpringBoot的两种方法:
- @ConfigurationProperties + @Component
假设有配置文件application.properties
mycar.brand=BYD mycar.price=100000
只有在容器中的组件,才会拥有SpringBoot提供的强大功能,所以Bean对象类注册成组件
下面的prefix是指属性前缀
@Component @ConfigurationProperties(prefix = "mycar") public class Car { ... }
- @EnableConfigurationProperties + @ConfigurationProperties
1.开启Car配置绑定功能
2.把这个Car这个组件自动注册到容器中
配置类:
@EnableConfigurationProperties(Car.class) public class MyConfig { //... }
Car类:
@ConfigurationProperties(prefix = "mycar") public class Car { //... }
HelloController类:
@RestController public class HelloController { @Autowired Car car; @RequestMapping("/car") public Car car(){ return car; } @RequestMapping("/hello") public String handle01(){ return "Hello,Spring Boot 2!"+"你好"; } }
这里我写了个控制层,运行结果如下:
可以看出确实将properties文件内的内容封装了。
总结
以上就是SpringBoot的一些底层注解的讲解。