容器功能–注解
Spring 注入组件的注解
@Component、@Controller、@Service、@Repository
说明: 这些在Spring 中的传统注解仍然有效,通过这些注解可以给容器注入组件
案例演示
- 创建quickstart\src\main\java\com\nlc\springboot\bean\A.java
其他的就不做演示了
- 在quickstart\src\main\java\com\nlc\springboot\MainApp.java 获取, 完成测试
@Configuration
应用实例
传统方式应用实例
说明: 演示在SpringBoot, 如何通过@Configuration 创建配置类来注入组件
回顾传统方式如何通过配置文件注入组件
1.创建quickstart\src\main\java\com\nlc\springboot\bean\Monster.java
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 + '\'' + '}'; } }
- 创建quickstart\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"> <!--配置了Monster bean--> <bean id="monster03" class="com.nlc.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>
使用SpringBoot 的@Configuration 添加/注入组件
- 创建quickstart\src\main\java\com\nlc\springboot\config\BeanConfig.java
程序员可以通过@Bean 注解注入bean对象到容器。
当一个类被 @Configuration 标识,该类-Bean 也会注入容器。
//@Configuration 标识这是一个配置类: 等价配置文件 @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") 可以每次返回新的对象,就多例. */ //@Bean(name = "monster_nmw") @Bean //@Scope("prototype") public Monster monster01() { return new Monster(200, "牛魔王", 500, "疯魔拳"); } }
2.修改MainApp.java , 从配置文件/容器获取bean , 并完成测试
public static void main(String[] args) { //启动springboot应用程序/项目 ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args); //1. ioc.getBean("monster01", Monster.class) 是从BeanConfig 配置类/容器获取bean实例 //2. 默认是单列模式, 所以monster01 == monster02 //获取BeanConfig 配置类的组件/bean 实例 Monster monster01 = ioc.getBean("monster01", Monster.class); System.out.println(monster01); Monster monster02 = ioc.getBean("monster01", Monster.class); System.out.println(monster01 == monster02); }
- 也可以通过Debug 来查看ioc 容器是否存在monster01 Bean 实例
beanDefinitionMap, 只是存放了bean 定义信息, 真正存放Bean 实例的在singleonObjectis的Map 中, 对于非单例,是每次动态反射生成的实例
@Configuration 注意事项和细节
- 配置类本身也是组件, 因此也可以获取, 测试修改MainApp.java
public static void main(String[] args) { ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args); //1. ioc.getBean("monster01", Monster.class) 是从BeanConfig 配置类/容器获取bean 实例 //2. 默认是单列模式, 所以monster01 == monster02 //获取BeanConfig 配置类的组件/bean 实例 Monster monster01 = ioc.getBean("monster01", Monster.class); System.out.println(monster01); Monster monster02 = ioc.getBean("monster01", Monster.class); System.out.println(monster01 == monster02); //配置类本身也是组件, 因此也可以获取 BeanConfig beanConfig = ioc.getBean(BeanConfig.class); System.out.println("beanConfig= " + beanConfig); }
- SpringBoot2 新增特性: proxyBeanMethods 指定Full 模式和Lite 模式
修改quickstart\src\main\java\com\nlc\springboot\config\BeanConfig.java
/** * * 1. proxyBeanMethods:代理bean的方法 * * (1) Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的, 是代理方式】 * * (2) Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的, 是非代理方式】 * * (3) 特别说明: proxyBeanMethods 是在 调用@Bean方法 才生效,因此,需要先获取BeanConfig 组件,再调用方法 * * 而不是直接通过 SpringBoot 主程序得到的容器来获取bean, 注意观察直接通过ioc.getBean() 获取Bean, proxyBeanMethods 值不会生效 * * (4) 如何选择: 组件依赖必须使用Full模式默认。如果不需要组件依赖使用 Lite模式 * * (5) Lite模 也称为轻量级模式,因为不检测依赖关系,运行速度快 */ //@Configuration 标识这是一个配置类: 等价配置文件 @Configuration(proxyBeanMethods = false) 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") 可以每次返回新的对象,就多例. */ //@Bean(name = "monster_nmw") @Bean //@Scope("prototype") public Monster monster01() { return new Monster(200, "牛魔王", 500, "疯魔拳"); } }
- 修改quickstart\src\main\java\com\nlc\springboot\MainApp.java
@SpringBootApplication(scanBasePackages = "com.nlc") public class MainApp { public static void main(String[] args) { //启动SpringBoot 应用程序 ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args); //1. ioc.getBean("monster01", Monster.class) 是从BeanConfig 配置类/容器获取bean实例 //2. 默认是单列模式, 所以monster01 == monster02 //获取BeanConfig 配置类的组件/bean 实例 Monster monster01 = ioc.getBean("monster01", Monster.class); System.out.println(monster01); Monster monster02 = ioc.getBean("monster01", Monster.class); System.out.println(monster01 == monster02); //配置类本身也是组件, 因此也可以获取,monster01 != monster02 //上面配置了@Configuration(proxyBeanMethods = false),获取到的都是新创建的 BeanConfig beanConfig = ioc.getBean(BeanConfig.class); System.out.println("beanConfig= " + beanConfig); Monster monster03 = beanConfig.monster01(); Monster monster04 = beanConfig.monster01(); System.out.println("monster03 == monster04 : " + (monster03 == monster04)); } }
- 配置类可以有多个, 就和Spring 可以有多个ioc 配置文件是一个道理.
创建quickstart\src\main\java\com\nlc\springboot\config\BeanConfig2.java
@Configuration public class BeanConfig2 { @Bean public Monster monster100() { return new Monster(200, "牛魔王~~", 500, "芭蕉扇"); } }
完成测试quickstart\src\main\java\com\nlc\springboot\MainApp.java
@SpringBootApplication public class MainApp { public static void main(String[] args) { //启动SpringBoot 应用程序 ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args); Monster monster100 = ioc.getBean("monster100", Monster.class); System.out.println(monster100); } }