day02-容器功能
容器功能
1.Spring注入组件的注解
Spring中的传统注解@Component、@Controller、@Service、@Repository,在SpringBoot中仍然有效。
2.@Configuration
@Configuration是 Spring 3.0 添加的一个注解,用来代替原先 Spring 中的 applicationContext.xml 容器配置文件,所有这个配置文件里面能做到的事情都可以通过这个注解所在类来进行注册。
在SpringBoot项目中,依然可以使用Spring的容器文件来注入bean/获取bean,但是不推荐使用
2.1应用实例
例子:使用SpringBoot的注解@Configuration添加/注入组件
(1)Monster.java
package com.li.springboot.bean;
/**
* @author 李
* @version 1.0
*/
public class Monster {
private Integer id;
private String name;
private Integer age;
private String skill;
//省略无参,全参构造器,getter,setter以及toString方法
}
(2)配置类:BeanConfig.java
package com.li.springboot.config;
import com.li.springboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* @author 李
* @version 1.0
*
* 1.@Configuration注解标识这是一个配置类,等价于spring的容器配置文件
* 2.这时我们可以通过@Bean注解注入Bean对象到容器中
* 3.当一个类被@Configuration标识,这个类也会被注入到容器中,因此也能在容器中获取这个类对象
*/
@Configuration
public class BeanConfig {
/**
* 1.@Bean表示给容器添加了一个组件,即Monster的bean对象
* 2.name = "monster_n1" 在配置,注入Bean时指定的名字/id,如果没有设置,
* 就使用方法名 monster01() :作为Bean的名字/id
* 3.Monster :方法的返回类型就是注入的bean类型
* 4.new Monster(200,"牛魔王",500,"芭蕉扇") 就是注入到容器中的具体 bean信息
* 5.默认为单例对象,如果要做成多例的,需要添加注解@Scope("prototype")
*/
@Bean(name = "monster_n1")
public Monster monster01() {
return new Monster(200, "牛魔王", 500, "芭蕉扇");
}
}
(3)MainApp.java
package com.li.springboot;
import com.li.springboot.bean.Monster;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author 李
* @version 1.0
*/
@SpringBootApplication(scanBasePackages = {"com.li"})
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext ioc =
SpringApplication.run(MainApp.class, args);
Monster monster_n1 = ioc.getBean("monster_n1", Monster.class);
Monster monster_n2 = ioc.getBean("monster_n1", Monster.class);
System.out.println("monster_n1=" + monster_n1
+ ",n1.hashCode=" + monster_n1.hashCode());
System.out.println("monster_n2=" + monster_n2
+ ",n2.hashCode=" + monster_n2.hashCode());
}
}
测试结果:成功注入容器,并且默认为单例对象
monster_n1=Monster{id=200, name='牛魔王', age=500, skill='芭蕉扇'},n1.hashCode=1532800776
monster_n2=Monster{id=200, name='牛魔王', age=500, skill='芭蕉扇'},n2.hashCode=1532800776
2.2注意事项和细节
(1)配置类本身也是组件,因此也可以在容器中获取,并且默认也是单例的
(2)SpringBoot2新增特性:proxyBeanMethods--代理 bean 的方法。
ProxyBeanMethods 可以指定 Full 模式和 Lite 模式
Full模式:
(proxyBeanMethods = true),保证修修饰的配置类中,每个@Bean 方法被调用多少次返回的组件都是单实例的,是代理方式Lite模式:
(proxyBeanMethods = false),保证修饰的配置类中,每个@Bean方法被调用多少次返回的组件都是新创建的,多例对象,是非代理方式特别说明:proxyBeanMethods 在调用 @Bean 方法时才生效,因此需要先获取BeanConfig 组件,再调用方法。而不是直接通过SpringBoot 主程序得到的容器来获取bean,直接通过ioc.getBean() 获取 Bean, proxyBeanMethods 值并不会生效
如何选择: 组件依赖必须使用 Full 模式(默认),如果不需要组件依赖使用 Lite 模式。
Lite 模 也称为轻量级模式,因为不检测依赖关系,运行速度快
(3)配置类可以有多个,就和Spring可以有多个容器配置文件一样
例子:测试proxyBeanMethods--代理 bean 的方法。
以2.1的代码为例,Monster.java不变
(1)修改配置类的注解为@Configuration(proxyBeanMethods = true),其他不变
(2)修改MainApp.java:
package com.li.springboot;
import ...
/**
* @author 李
* @version 1.0
*/
@SpringBootApplication(scanBasePackages = {"com.li"})
public class MainApp {
public static void main(String[] args) {
//启动SpringBoot应用程序/项目
ConfigurableApplicationContext ioc =
SpringApplication.run(MainApp.class, args);
//1.先得到BeanConfig组件
BeanConfig beanConfig = ioc.getBean(BeanConfig.class);
//2.通过beanConfig对象调用方法才能生效!!
Monster monster_01 = beanConfig.monster01();
Monster monster_02 = beanConfig.monster01();
System.out.println("monster_01=" + monster_01
+ ",hashcode=" + monster_01.hashCode());
System.out.println("monster_02=" + monster_02
+ ",hashcode=" + monster_02.hashCode());
}
}
注意:proxyBeanMethods 在调用 @Bean 方法时才生效,因此需要先获取BeanConfig 组件,再调用方法。
测试结果:哈希值相同,说明获取的对象是同一个,为单例对象
monster_01=Monster{id=200, name='牛魔王', age=500, skill='芭蕉扇'},hashcode=1075996552
monster_02=Monster{id=200, name='牛魔王', age=500, skill='芭蕉扇'},hashcode=1075996552
(3)将配置类的注解改为:@Configuration(proxyBeanMethods = false),然后重新测试
测试结果:每次返回的对象都是新的对象,即多例对象
monster_01=Monster{id=200, name='牛魔王', age=500, skill='芭蕉扇'},hashcode=1164699452
monster_02=Monster{id=200, name='牛魔王', age=500, skill='芭蕉扇'},hashcode=594916129
3.@Import
@Import 是 Spring 3.0 添加的新注解,用来修饰 @Configuration 注解修饰的类,在 Spring Boot 里面应用很多,它可以将普通类导入到spring容器中做管理。
源码:
package org.springframework.context.annotation;
import ...
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
Class<?>[] value();
}
通过源码可以看到该注解可以指定class的数组,通过该数组注入指定类型的Bean
3.1应用实例
(1)创建两个Bean,Dog.java和Cat.java
package com.li.springboot.bean;
/**
* @author 李
* @version 1.0
*/
public class Dog {
}
package com.li.springboot.bean;
/**
* @author 李
* @version 1.0
*/
public class Cat {
}
(2)配置类BeanConfig.java
package com.li.springboot.config;
import com.li.springboot.bean.Cat;
import com.li.springboot.bean.Dog;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author 李
* @version 1.0
* 通过@Import方式注入了组件,默认的组件名字/id为类型的全类名:
* com.li.springboot.bean.Dog 和 com.li.springboot.bean.Cat
*/
@Import({Dog.class, Cat.class})
@Configuration//标识这是一个配置类,等价于配置文件
public class BeanConfig {
}
(3)MainApp.java
package com.li.springboot;
import ...
/**
* @author 李
* @version 1.0
*/
@SpringBootApplication(scanBasePackages = {"com.li"})
public class MainApp {
public static void main(String[] args) {
//启动SpringBoot应用程序/项目
ConfigurableApplicationContext ioc =
SpringApplication.run(MainApp.class, args);
//测试@Import
Dog dogBean = ioc.getBean(Dog.class);
Cat catBean = ioc.getBean(Cat.class);
System.out.println("dogBean=" + dogBean);
System.out.println("catBean=" + catBean);
}
}
测试结果:
dogBean=com.li.springboot.bean.Dog@12477988
catBean=com.li.springboot.bean.Cat@2caf6912
4.@Conditional
条件装配:满足 Conditional 指定的条件,才进行组件注入
它可以修饰类,接口或者枚举类型,还可以修饰在方法上
@Conditional 是一个根注解,它的下面有很多扩展注解
| @Conditional扩展注解 | 作用 |
|---|---|
| @ConditionalOnJava | 当JVM版本为指定的版本范围时触发实例化 |
| @ConditionalOnBean | 当容器中至少存在一个指定name或class的Bean时,进行实例化 |
| @ConditionalOnMissingBean | 当容器中指定name或class的Bean都不存在时,进行实例化 |
| @ConditionalOnExpression | 基于SpEL表达式的条件判断,当为true的时候进行实例化 |
| @ConditionalOnClass | 当类路径下至少存在一个指定的class时,进行实例化 |
| @ConditionalOnMissingClass | 当容器中指定class都不存在时,进行实例化 |
| @ConditionalOnSingleCandidate | 当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化 |
| @ConditionalOnProperty | 当指定的属性有指定的值时进行实例化 |
| @ConditionalOnResource | 当类路径下有指定的资源时触发实例化 |
| @ConditionalOnWebApplication | 当项目是一个Web项目时进行实例化 |
| @ConditionalOnNotWebApplication | 当项目不是一个Web项目时进行实例化 |
| @ConditionalOnJndi | 在JNDI存在的条件下触发实例化 |
4.1应用实例
演示在SpringBoot中通过@ConditionalOnBean来注入组件
(1)指定条件:当容器中有name="monster_nmw"组件时,才注入dog01,代码如下:
package com.li.springboot.config;
import ...
/**
* @author 李
* @version 1.0
*/
@Configuration
public class BeanConfig {
@Bean
public Monster monster01() {
return new Monster(200, "牛魔王", 500, "芭蕉扇");
}
/**
* 1.@ConditionalOnBean(name = "monster_nmw")
* 表示当容器中存在id为monster_nmw的Bean时(对类型不做约束),
* dog01这个Dog Bean才能注入到容器中
* 2.如果不符合条件,则不能注入容器
*/
@Bean
@ConditionalOnBean(name = "monster_nmw")
public Dog dog01() {
return new Dog();
}
}
(2)MainApp.java
package com.li.springboot;
import ...
/**
* @author 李
* @version 1.0
*/
@SpringBootApplication(scanBasePackages = {"com.li"})
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext ioc =
SpringApplication.run(MainApp.class, args);
//演示@ConditionalOnBean的使用
Dog dog01 = ioc.getBean("dog01", Dog.class);
System.out.println("dog01=" + dog01);
}
}
测试结果:运行出错,因为容器中没有名为monster_nmw的 Bean,因此不能注入Dog Bean,也就无法通过getBean获取到Dog Bean对象。

5.@ImportResource
作用:原生功能配置文件引入,可以直接导入Spring传统的beans.xml到配置类中,可以认为是SpringBoot对Spring的兼容。
day02-容器功能的更多相关文章
- Java工作流引擎的测试容器-功能-使用方法-注意事项
工作流引擎的测试容器-功能-使用方法-注意事项 关键字 Ccbpm, ccflow,jflow,工作流引擎,工作流引擎测试容器,表单引擎 功能说明 工作流的测试容器是为了解决手工模拟人工登录模式下测试 ...
- springboot注解之容器功能
添加组件 @Configuration.@Bean //以swagger为例 @Configuration(proxyBeanMethods = false) @EnableSwagger2 //使用 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法一:使用XML文件定义beans之间的依赖注入关系
XML-based configuration metadata(使用XML文件定义beans之间的依赖注入关系) 第一部分 编程思路概述 step1,在XML文件中定义各个bean之间的依赖关系. ...
- spring cloud: Hystrix(四):feign类似于hystrix的断容器功能:fallback
spring cloud: Hystrix(四):feign使用hystrix @FeignClient支持回退的概念:fallback方法,这里有点类似于:@HystrixCommand(fallb ...
- Spring 系列教程之容器的功能
Spring 系列教程之容器的功能 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单的了解,在前面的章节中我们一直以 BeanFacotry 接口以及它的默认实现类 XmlBea ...
- Spring源码分析(十九)容器的功能扩展概览
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单 ...
- 在Linux和Windows的Docker容器中运行ASP.NET Core
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott H ...
- Asp.net 面向接口可扩展框架之核心容器(含测试代码下载)
新框架的容器部分终于调通了!容器实在太重要了,所以有用了一个名词叫“核心容器”. 容器为什么那么重要呢?这个有必要好好说道说道. 1.首先我们从框架名称面向接口编程说起,什么是面向接口编程?(这个度娘 ...
- 初识Docker和Windows Server容器
概览 伴随着Windows Server 2016 Technical Preview 3 (TP3)版本的发布,微软首次提供了Windows平台下地原生容器.它集成了Docker对Windows S ...
- Jetty嵌入式Web容器攻略
Jetty是一个用 Java 实现.开源.基于标准的,并且具有丰富功能的 Http 服务器和 Web 容器.Jetty中应用最广泛的一项功能就是可以作为嵌入式Web容器. 在开发阶段,可以使用Jett ...
随机推荐
- element ui 分页
修改选中页码的样式: .el-pager .active{ color:red !important;//选中 } .el-pager .number:hover{ color:red !import ...
- 进程间通信测试-signal
截图 代码 #include <stdio.h> #include <unistd.h> #include <signal.h> #include <stri ...
- synchronized同步
package com.lei.syn; import java.util.ArrayList; import java.util.List; //线程不安全集合 public class Unsaf ...
- Github页面图片加载失败
Window系统下 还可以使用ipconfig/flush对本地DNS缓存进行一次刷新,如果遇到网络异常,可能是DNS缓存的问题,刷新一下,步骤. windows开始→运行→输入:CMD 按回车键,打 ...
- omcat启动Publishing failed with multiple errors
新安装一个tomcat插件.启动的时候就弹错误框.但tomcat还能使用. Publishingfailedwithmultipleerrors Resource is out of sync wit ...
- noi 1.1 2 输出第二个整数
描述 输入三个整数,把第二个输入的整数输出. 输入 只有一行,共三个整数,整数之间由一个空格分隔.整数是32位有符号整数. 输出 只有一行,一个整数,即输入的第二个整数. 样例输入 123 456 7 ...
- Linux日常指令
Linux: https://man.linuxde.net/ Linux命令大全 基础指令 终端输入: #shutdown -h now : 立即关机 #ls: 显示路径下所有的文件: ...
- LCP 34. 二叉树染色
class Solution: def maxValue(self, root: TreeNode, k: int) -> int: def dfs(root): # 空节点价值全为0 res ...
- Jmeter前置处理器和后置处理器的使用
一.JMETER基本概念 1. 测试计划:顶级菜单,代表一个测试计划: 2. 线程组:代表一个要测试的场景(各种相关的交易集合),对于性能测试来说可以指定多少个用户完成这个场景的内容,对于自动化测试 ...
- java中list对象不同属性去重合并
需求:将list中对象的不同属性对应的值去重后,赋值给另一个属性! 实现效果如下图: