添加组件
@Configuration
之前用spring-xml文件声明组件
<bean id="user01" class="com.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="dog1" class="com.boot.bean.Pet">
<property name="name" value="wangcai"></property>
</bean>
SpringBoot用@Configuration声明一个配置类
/**
* 1.Configuration声明是配置类;配置类也是一个组件;
* 2.@Bean修饰方法:注册组件,方法名是id,返回值是class;
* 3.@Bean("name"):可以在注解里写明方法名,这样就不会用方法名做id了
* 4.@Configuration(proxyBeanMethods=true):是否是代理bean的方式
* */
@Configuration(proxyBeanMethods=true)
public class MyConfig {
@Bean
public User user01(){
return new User("zhangsan",18);
}
@Bean
public Pet dog1(){
return new Pet("wangcai");
}
}
组件注册方法调用是否获取单例bean
因为proxyBeanMethods=true,增强后springBoot会检查容器中是否已经有这个组件,没有再新建这个bean——为了保持单例bean。
这种情况下无论配置类中组件注册方法被调用多少次,都只会获取之前注册在容器里的单例bean
MyConfig bean = run.getBean(MyConfig.class); //拿到配置类
User user = bean.user01();
User user1 = bean.user01();
System.out.println("user:"+(user==user1));
结果:
但是如果proxyBeanMethods=false,那结果就是false了。
所以什么时候代理为true,什么时候为false?
组件依赖:User组件依赖了Pet组件
public class User {
private String name;
private int age;
private Pet pet;
}
@Configuration(proxyBeanMethods=true)
public class MyConfig {
@Bean
public User user01(){
User user = new User("zhangsan",18);
user.setPet(dog1()); //User组件中有(依赖)Pet组件
return user;
}
@Bean
public Pet dog1(){
return new Pet("wangcai");
}
}
User user2 = run.getBean("user01",User.class);
Pet dog03 = run.getBean("dog1",Pet.class);
System.out.println("用户宠物是否和容器中一致?"+(user2.getPet()==dog03));
Full模式(proxyBeanMethods=true):
Lite模式(proxyBeanMethods=fasle):
proxyBeanMethods的作用是:
springBoot会检查容器中是否已经有这个组件,容器中没有再新建这个bean。
因此两种模式使用的情况:
1.Full:组件依赖时以下代码能获取同一个pet——适用于有组件依赖的情况。
2.Lite:不是同一pet;但是会减少判断,启动起来快一些,因此适用于只注册组件,也没有组件依赖的情况
直接容器里取默认单例bean
默认单例bean:
//返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class,args);
//从容器中获取组件
Pet dog01 = run.getBean("dog1", Pet.class);
Pet dog02 = run.getBean("dog1", Pet.class);
System.out.println(dog01==dog02);
结果:
以前的@Bean,@Component,@Service,@Repository依旧可以用,和主程序类写在同级包下就可以扫描到。
@Import
可以导入一个数组的组件;可以是自己写的组件也可以是第三方组件。
/**
* @Import({User.class, SimpleDBNameResolver.class}) IOC容器自动创建出这两种类型的组件,组件的名字就是全类名
* */
@Import({User.class, SimpleDBNameResolver.class})
@Configuration(proxyBeanMethods=true)
public class MyConfig {
@Bean
public User user01(){
User user = new User("zhangsan",18);
user.setPet(dog1());
return user;
}
}
主程序验证注入情况:
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class,args);
//拿到IOC容器中所有User类型的Bean
String[] beanNamesForType = run.getBeanNamesForType(User.class);
for (String s:beanNamesForType) {
System.out.println(s);
}
System.out.println("---------------------------");
//第三方组件是否创建成功
SimpleDBNameResolver sdb = run.getBean(SimpleDBNameResolver.class);
System.out.println(sdb);
}
}
验证结果:
@Conditional 条件装配
满足条件则进行组件注入,可以写在类上也可以写在方法上。
以@ConditionalOnBean举例:
@Configuration(proxyBeanMethods=true)
public class MyConfig {
//容器中有dog1这个名字的组件时,再注入user01这个组件
@ConditionalOnBean(name = "dog1")
@Bean
public User user01(){
User user = new User("zhangsan",18);
user.setPet(dog1());
return user;
}
//@Bean
public Pet dog1(){
return new Pet("wangcai");
}
}
主程序:
public static void main(String[] args) {
//返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class,args);
boolean dog = run.containsBean("dog1");
System.out.println("容器中有无dog1:"+dog);
boolean user = run.containsBean("user01");
System.out.println("容器中有无user01:"+user);
}
答案:
@ImportResource
导入原生spring配置文件
Ex.原来用xml文件声明的bean不想一个一个用@Bean去改,可以再要用xml里的bean的类上写@ImportResource注解指定xml位置后,就可以获取xml里的bean了。
原生配置——beans.xml:
<bean id="user02" class="com.ttz.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="dog2" class="com.ttz.boot.bean.Pet">
<property name="name" value="wangcai"></property>
</bean>
想调用beans.xml里bean的类写上@ImportResource后重新解析xml文件:
@ImportResource("classpath:beans.xml")
public class MyConfig {
//略
}
主程序看是否解析xml:
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class,args);
System.out.println("------@ImportResource-------------");
boolean dog2 = run.containsBean("dog2");
System.out.println("容器中有无dog2:"+dog2);
boolean user2 = run.containsBean("user02");
System.out.println("容器中有无user02:"+user2);
}
}
结果:
配置绑定
@ConfigurantionProperties
properties文件的属性一一解析到JavaBean中。
注意:适合核心配置文件application.properties绑定在一起
1.@Configuration+@Component:加在容器中
properties配置文件:
mycar.brand=BYD
mycar.price=100000
JavaBean:
//只有在容器中的组件才会拥有容器提供的功能,ex:配置绑定
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
//省略构造方法,getter,setter和toString()
}
只有注册成组件之后,才能实现容器提供的配置绑定功能;
prefix = “mycar”:指的是匹配properties文件中的前缀为mycar的属性。
Controller看效果:
@ResponseBody
@Controller
public class HelloController {
@Autowired
Car car; //解析完就已经放进容器里了,所以可以直接在容器中获取bean
@RequestMapping("/car")
public Car car(){
return car;
}
}
结果:
2.@Configuration+@EnableConfigurationProperties:配置绑定开启
用于配置类
javaBean:
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
//省略构造方法,getter,setter和toString()
}
配置类:
@EnableConfigurationProperties(Car.class)
//1.开启car配置绑定功能
//2.把car组件自动注册到容器中
public class MyConfig {
//略
}
结果: