SpringBoot框架学习笔记(二):容器功能相关注解详解
1 Spring 注入组件的注解
@Component、@Controller、 @Service、@Repository这些在 Spring 中的传统注解仍然有效,通过这些注解可以给容器注入组件
2 @Configuration
2.1 应用实例
需求说明: 演示在 SpringBoot, 如何通过@Configuration 创建配置类来注入组件
回顾传统方式如何通过配置文件注入组件
(1)创建 com\springboot\bean\Monster.java
package com.springboot.bean;
public class Monster {
private Integer id;
private String name;
private Integer age;
private String skill;
public Monster(Integer id, String name, Integer age, String skill) {
this.id = id;
this.name = name;
this.age = age;
this.skill = skill;
}
public Monster() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
@Override
public String toString() {
return "Monster{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", skill='" + skill + '\'' +
'}';
}
}
(2)创建 src\main\resources\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="monster03" class="com.springboot.bean.Monster">
<property name="name" value="牛魔王~"></property>
<property name="age" value="5000"></property>
<property name="skill" value="芭蕉扇~"></property>
<property name="id" value="1000"></property>
</bean>
</beans>
(3)在主程序中进行测试
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster monster = ioc.getBean("monster03", Monster.class);
System.out.println("monster=" + monster);
运行结果
使用 SpringBoot 的@Configuration 添加/注入组件
(1)创建 src\main\java\com\springboot\config\BeanConfig.java
package com.springboot.config;
import com.springboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 1. @Configuration 标识这是一个配置类, 等价于配置文件
* 2. 程序员可以通过@Bean 注解注入bean对象到容器
* 3. 当一个类被 @Configuration 标识,该类-Bean 也会注入容器
*/
@Configuration
public class BeanConfig {
/**
* 1. @Bean : 给容器添加组件, 就是Monster bean
* 2. monster01() : 默认方法名monster01 作为Bean的名字/id
* 3. Monster : 注入类型, 注入bean的类型是Monster
* 4. new Monster(200,"牛魔王",500,"疯魔拳") 注入到容器中具体的Bean信息
* 5. @Bean(name = "monster_nmw") : 在配置、注入Bean指定名字/id monster_nmw
* 6. 默认是单例注入
* 7. 通过 @Scope("prototype") 这样设置就会让每次getBean()返回新的对象,即多例.
*/
//@Bean(name = "monster_nmw")
@Bean
//@Scope("prototype")
public Monster monster01() {
return new Monster(200, "牛魔王", 500, "疯魔拳");
}
}
(2)修改 MainApp.java , 从配置文件/容器获取 bean , 并完成测试
//启动springboot应用程序
ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);
//===演示 @Configuration====
Monster monster01 = ioc.getBean("monster01", Monster.class);
Monster monster02 = ioc.getBean("monster01", Monster.class);
System.out.println("monster01--" + monster01 + " " + monster01.hashCode());
System.out.println("monster02--" + monster02 + " " + monster02.hashCode());
运行结果
成功注入容器,且两次返回的对象的哈希值相同,可知返回的是同一个对象,即单例
2.2 @Configuration 注意事项和细节
(1)配置类本身也是组件, 因此也可以获取
//===演示 配置类也会被注入容器 ====
BeanConfig bean = ioc.getBean(BeanConfig.class);
System.out.println("bean--" + bean);
(2)pringBoot2 新增特性: proxyBeanMethods 指定 Full 模式 和 Lite 模式
proxyBeanMethods:代理bean的方法
- proxyBeanMethods = true 表示Full模式,保证每个@Bean方法被调用多少次返回的组件都是单实例的, 是代理方式
- proxyBeanMethods = false 表示Lite模式,每个@Bean方法被调用多少次返回的组件都是新创建的, 是非代理方式
- 特别说明: proxyBeanMethods 是在 调用@Bean方法才生效,因此,需要先获取BeanConfig 组件,再调用方法。而不是直接通过 SpringBoot 主程序得到的容器来获取bean, 直接通过ioc.getBean() 获取Bean, proxyBeanMethods 值并没有生效
- 如何选择: 组件依赖必须使用Full模式默认。如果不需要组件依赖使用 Lite模式。默认为 true
- Lite模 也称为轻量级模式,因为不检测依赖关系,运行速度快
// 指定Lite模式
@Configuration(proxyBeanMethods = false)
public class BeanConfig {
主程序测试
//===演示@Configuration(proxyBeanMethods = xxx)
//1. 先得到BeanConfig组件
BeanConfig beanConfig = ioc.getBean(BeanConfig.class);
Monster monster_01 = beanConfig.monster01();
Monster monster_02 = beanConfig.monster01();
//
System.out.println("monster_01-" + monster_01 + " " + monster_01.hashCode());
System.out.println("monster_02-" + monster_02 + " " + monster_02.hashCode());
//直接通过ioc.getBean() 获取Bean, proxyBeanMethods 值并没有生效
Monster monster01 = ioc.getBean("monster01", Monster.class);
Monster monster02 = ioc.getBean("monster01", Monster.class);
System.out.println("monster01-" + monster01 + " " + monster01.hashCode());
System.out.println("monster02-" + monster02 + " " + monster02.hashCode());
运行结果
(3)配置类可以有多个, 就和 Spring 可以有多个 ioc 配置文件是一个道理。但是bean的id不能重复
3 @Import
通过查看@Import 源码可以了解,该注解可以通过指定一个 class类型的数组, 来注入指定类型的Bean
public @interface Import {
Class<?>[] value();
}
通过@Import 方式注入的组件, 默认组件id就是对应类型的全类名
1.3.1 应用实例
需求说明: 演示在 SpringBoot, 如何通过 @Import 来注入组件
(1)创建 bean\Cat.java 和 bean\Dog.java
package com.springboot.bean;
public class Cat {
}
package com.springboot.bean;
public class Dog {
}
(2)修改 BeanConfig.java 通过@Import 注入组件
// 这样配置即可将 Dog,Cat注入组件
// 默认id为com.springboot.bean.Dog 和 com.springboot.bean.Cat
@Import({Dog.class, Cat.class})
(3)修改 MainApp.java 完成测试
//===测试@Import 使用
Dog dogBean = ioc.getBean(Dog.class);
Cat catBean = ioc.getBean(Cat.class);
System.out.println("dogBean--" + dogBean);
System.out.println("catBean--" + catBean);
运行结果
4 @Conditional
4.1 @Conditional 介绍
(1)条件装配:满足 Conditional 指定的条件,则进行组件注入
(2)@Conditional 是一个根注解,下面有很多扩展注解
4.2 应用实例
需求说明: 演示在 SpringBoot, 如何通过 @ConditionalOnBean 来注入组件,只有在容器中有 name = monster_nmw 的组件时,才注入 dog01
代码实现:
修改 BeanConfig.java , 加入@ConditionalOnBean 条件约束,并完成测试
@Bean
/**
* 1. @ConditionalOnBean(name = "monster_nmw") 表示
* 2. 当容器中有一个Bean , 名字是monster_nmw (类型不做约束), 就注入dog01这个Dog bean
* 3. 如果没有 名字是monster_nmw Bean 就不注入dog01这个Dog bean
* 4. @ConditionalOnMissingBean(name = "monster_nmw") 表示在容器中,
* 没有 名字/id 为 monster_nmw 才注入dog01这个Bean
* 5. @ConditionalOnBean(name = "monster_nmw") 也可以放在配置类上
* 表示对该配置类的所有要注入的组件,都进行条件约束.
*/
@ConditionalOnBean(name = "monster_nmw")
//@ConditionalOnMissingBean(name = "monster_nmw")
public Dog dog01() {
return new Dog();
}
特别说明:@ConditionalOnBean(name = "monster_nmw") 也可以放在配置类上,表示对该配置类的所有要注入的组件,都进行条件约束
主方法中加入测试
//===演示 @ConditionalOnBean 使用 start ====
Dog dog01 = ioc.getBean("dog01", Dog.class);
System.out.println("dog01--" + dog01);
运行结果
由运行结果可知,由于容器中没有 name = monster_nmw 的组件,所以 dog01 没有被注入容器
5 @ImportResource
作用:原生配置文件引入, 也就是可以直接导入 Spring 传统的 beans.xml ,可以认为是 SpringBoot 对 Spring 容器文件的兼容.
5.1 @ImportResource 应用实例
需求: 将 beans.xml 导入到 BeanConfig.java 配置类, 并测试是否可以获得 beans.xml 注入/配置的组件 。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="monster03" class="com.springboot.bean.Monster">
<property name="name" value="牛魔王~"></property>
<property name="age" value="5000"></property>
<property name="skill" value="芭蕉扇~"></property>
<property name="id" value="1000"></property>
</bean>
</beans>
(1)创建新的 BeanConfig3.java 来测试, 使用@ImportResource 导入 beans.xml
package com.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
//导入beans.xml - 就可以获取到beans.xml 中配置的bean
//可以简写为@ImportResource("classpath:beans.xml")
//可以同时导入多个配置文件,如下
//@ImportResource(locations = {"classpath:beans.xml","classpath:beans02.xml"})
@ImportResource(locations = "classpath:beans.xml")
public class BeanConfig3 {
}
(2)在 MainApp.java 测试
//演示@ImportResource 使用 start===
System.out.println("monster03 bean 是否存在-" + ioc.containsBean("monster03"));
运行结果
6 @ConfigurationProperties 配置绑定
说明:使用 Java 读取到 SpringBoot 核心配置文件 application.properties 的内容, 并且把它封装到 JavaBean 中
6.1 应用实例
需求: 将 application.properties 指定的 k-v 和 JavaBean 绑定
(1)在 application.properties 文件中指定k-v
#设置Furn的属性k-v
#前面的 furn01 是用于指定不同的绑定对象,这样可以在绑定Furn bean属性时
#通过 furn01 前缀进行区分
#furn01.id 中的 id 就是要绑定的 Furn bean的属性值
furn01.id=100
furn01.name=TV
furn01.price=1000.9
(2)创建 bean\furn.java,使用 @ConfigurationProperties 注解完成配置绑定
package com.springboot.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "furn01")
public class Furn {
private Integer id;
private String name;
private Double price;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
(3) controller/FurnController.java
package com.springboot.controller;
import com.springboot.bean.Furn;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
@Controller
public class FurnController {
// 装配到FurnController
@Resource
private Furn furn;
@RequestMapping("/furn")
@ResponseBody
public Furn furn(){
return furn;
}
}
(4)启动SpringBoot主程序,在浏览器中输入网址 localhost:8080/furn,完成测试。效果如下
(5)特别说明,在 Furn 类上注销 @Component 并 在 BeanConfig.java( 也 可 以 是 其 它 配 置 类 ) 配 置 @EnableConfigurationProperties(Furn.class) 或 @Import( Furn.class), 效果一样
6.2 注意事项和细节
(1)如果 application.properties 有中文, 需要转成 unicode 编码写入, 否则出现乱码
#设置属性 k-v
furn01.id=100
furn01.name=soft_chair\u6c99\u53d1!!
furn01.price=45678.9
(2)使用 @ConfigurationProperties(prefix = "furn01") 会提示如下信息, 但是不会影响使用
(3)解决 @ConfigurationProperties(prefix = "furn01") 提示信息, 在 pom.xml 增加以下依赖, 即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
原文地址:https://blog.csdn.net/2301_76144723/article/details/138400741
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!