SpringBoot---容器功能
1、组件添加
首先创建两个bean,一个叫User,一个叫Food。
以前在SSM中需要在配置文件中设置组件和属性注入。现在使用SpringBoot就可以用全代码方式实现整个过程。创建一个配置类,使用@Configuration注解标记,声明类为配置类。
/*
声明这个类是一个配置类。在里面完成配置文件完成的事情。这样的话,配置类也是项目的一个组件
经过输出发现他是一个动态代理CGLIB增强后的组件对象
Configuration注释里面提供了一个方法proxyBeanMethods【代理组件方法】,它的默认值是true
如果是true,那么在项目内通过调用配置类组件再调用配置方法获取到的对象都是同一个,就是代理对象调用方法
SpringBoot总会检查容器中有没有这个组件,有就拿出来给你,所以一直都是一个。保持组件单实例 Full模式
如果修改为false,那么通过配置类组件调用方法得到的对象不是同一个 Lite模式
*/
@Configuration(proxyBeanMethods = true)
public class MyConfig {
/*
使用Bean标签标识配置类方法,返回值就是组件类型,方法名就是组件id,返回的具体内容就是组件在容器中保存的对象。
想设置别的组件名可以在Bean注解里面设置value属性值就行
*/
@Bean
public User user01(){
return new User("hanfu","woman","123456");
}
@Bean
public Food beef(){
return new Food("beef","99");
}
}
然后来到主程序类MyApplication中,使用返回的run对象调用getBean方法获取IOC容器里面的组件。
经过输出查看,发现了注册的组件和配置组件。都是组件。并且验证了多次获取同一个组件id拿到的是不是同一个组件
在输出配置组件可以发现: com.boot.config.MyConfig$$EnhancerBySpringCGLIB$$7c4c3a02@7a26928a 是一个经过CGLIB增强的代理对象。
// 通过返回的IOC容器,调用方法获取组件
// SpringBoot里面,IOC容器里面的组件默认是单例的,在其他地方默认调用多少次都是同一个
User hanfu = run.getBean("user01", User.class);
User user01 = run.getBean("user01", User.class);
System.out.println(hanfu==user01);
MyConfig myConfig = run.getBean("myConfig", MyConfig.class);
System.out.println("myConfig = " + myConfig);
由于发现配置类也是组件,验证通过获取配置组件调用其中的方法得到的对象也是同一个。
Full模式【全配置】:每次调用组件都查看IOC容器有没有,启动的慢
Configuration注释里面提供了一个方法proxyBeanMethods【代理组件方法】,它的默认值是true 如果是true,那么在项目内通过调用配置类组件再调用配置方法获取到的对象都是同一个,就是代理对象调用方法 SpringBoot总会检查容器中有没有这个组件,有就拿出来给你,所以一直都是一个。保持组件单实例
现在user要吃饭,于是引入了food属性,构建了get、set。在配置类中user方法里调用了注册food的方法,user依赖了food。那么proxyBeanMethods值为true时,从容器中获取的组件food和使用user组件调用getfood方法得到的组件对象是同一个。值为false时,就不是同一个了
proxyBeanMethods值为true时就是full模式,在组件之间有依赖关系时,可以使用。能保证拿到的组件对象是同一个。
@Bean
public User user01(){
User user = new User("hanfu", "woman", "123456");
user.setFood(beef());
return user;
}
@Bean
public Food beef(){
return new Food("beef","99");
}
Lite模式【轻量级配置】:直接跳过查看步骤,启动的快
如果修改为false,那么通过配置类组件调用方法得到的对象不是同一个
proxyBeanMethods值为false是lite模式,如果只是注册组件,组件之间没有依赖关系,使用这个,SpringBoot启动的更快些
2、@Import导入组件
@Import注解使用时在声明后的组件上面,在里面需要的参数是一个class数组。在数组里面写上自己想导入容器的组件名.class。就是调用数组中类的无参构造构建一个对象作为组件,这个数组里面的类可以是自己写的也可以是依赖里面的,有需要加就加
使用
通过结果发现输出的组件是添加时类的全类名。
@Import({User.class, SimpleObjectIdResolver.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
结果
--------------分割线-------------
s = xlw.com.boot.bean.User
s = user01
s = com.fasterxml.jackson.annotation.SimpleObjectIdResolver
3、@Conditional条件装配
根据注解需要的条件对组件进行操作。
根据注解的名字不难看出注解代表的功能,在SpringBoot底层用了很多这种注解,辅助完成自动装配,使用这些注解判断当前类或方法存在或不存在某个条件。实现组件的装配。
这个注解可以在类和方法上用,在类上面用就是满足条件,类里面的组件就会自动装配进IOC容器里,否则就不在方法上就跟类一样的效果
注解的参数可以根据类型或者组件名。添加条件实现效果。
使用
在这里使用的注解的作用是,IOC容器中有user这个组件时才会创建下面两个组件,很明显没有这个组件。
@ConditionalOnBean(name = "user")
@Configuration(proxyBeanMethods = true)
public class MyConfig {
/*
使用Bean标签标识配置类方法,返回值就是组件类型,方法名就是组件id,返回的具体内容就是组件在容器中保存的对象。
想设置别的组件名可以在Bean注解里面设置value属性值就行
*/
@Bean
public User user01(){
User user = new User("hanfu", "woman", "123456");
user.setFood(beef());
return user;
}
@Bean
public Food beef(){
return new Food("beef","99");
}
主程序里
// 判断是不是有当前参数名的组件存在
boolean user01 = run.containsBean("user01");
boolean beef = run.containsBean("beef");
System.out.println("有没有组件user01" +user01);
System.out.println("有没有组件beef " + beef);
结果
有没有组件user01false
有没有组件beef false
将注解更改为@ConditionalOnMissingBean(name = "user"),即IOC容器里面没有组件user就创建这两个组件。
结果
有没有组件user01true
有没有组件beef true
到这里就不难理解自动装配,如果引入场景就为你创建组件,没有就不加载组件
4、@ImportResource引入配置文件
在很多项目外部依赖里面,还是会有组件在xml配置文件中注册好的,因为很多,不可能自己用的时候重新再写一遍。就能用这个注解@ImportResource引入外部文件,这样配置文件中的组件,也添加到当前的IOC容器中了
使用
@ImportResource("classpath:beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="niuniu" class="xlw.com.boot.bean.User">
</bean>
<bean id="huahua" class="xlw.com.boot.bean.User"></bean>
</beans>
结果
在当前的IOC里面存在这两个由配置文件注册的组件
boolean niuniu = run.containsBean("niuniu");
System.out.println("niuniu = " + niuniu);
boolean huahua = run.containsBean("huahua");
System.out.println("huahua = " + huahua);
niuniu = true
huahua = true
5、配置绑定
使用注解@ConfigurationProperties,能够把bean的属性和SpringBoot核心配置文件application.properties绑定在一起。用于设置属性值。
a)、已经注册为组件
首先要将类进行注册,然后是使用注解@ConfigurationProperties把组件和核心配置文件中指定的字段进行绑定
注解里面有不同的属性代表不同的绑定形式
@Component
@ConfigurationProperties(prefix = "children")
public class Children {
private String name;
private String age;
public Children() {
}
public Children(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Children{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
application.properties中
children.name="haha"
children.age="12"
现在已经把组件和配置文件绑定起来了,在控制器中自动注入,将数据返回致页面
@Autowired
private Children children;
@RequestMapping("/children")
public Children test02(){
return children;
}
最后拿到数据。
b)、没有注册为组件
有需要引入外部组件,将他和核心配置文件绑定。有的类并没有被注册为组件。就能 在配置类中 使用注解
@EnableConfigurationProperties(Children.class) 在参数中加入需要开启绑定功能的类
使用
现在bean并没有被注册为组件
@ConfigurationProperties(prefix = "children")
public class Children {
private String name;
private String age;
public Children() {
}
public Children(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Children{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
在配置类中
在类上面加上这一条语句,注册参数类为组件,同时开启绑定功能
@EnableConfigurationProperties(Children.class)
后面一样能拿到这个绑定后的结果