容器功能

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 的方法。

  1. ProxyBeanMethods 可以指定 Full 模式和 Lite 模式

    • Full模式:(proxyBeanMethods = true),保证修修饰的配置类中,每个@Bean 方法被调用多少次返回的组件都是单实例的,是代理方式

    • Lite模式:(proxyBeanMethods = false),保证修饰的配置类中,每个@Bean方法被调用多少次返回的组件都是新创建的,多例对象,是非代理方式

    • 特别说明:proxyBeanMethods 在调用 @Bean 方法时才生效,因此需要先获取BeanConfig 组件,再调用方法。而不是直接通过SpringBoot 主程序得到的容器来获取bean,直接通过ioc.getBean() 获取 Bean, proxyBeanMethods 值并不会生效

  2. 如何选择: 组件依赖必须使用 Full 模式(默认),如果不需要组件依赖使用 Lite 模式。

  3. 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

  1. 条件装配:满足 Conditional 指定的条件,才进行组件注入

  2. 它可以修饰类,接口或者枚举类型,还可以修饰在方法上

  3. @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-容器功能的更多相关文章

  1. Java工作流引擎的测试容器-功能-使用方法-注意事项

    工作流引擎的测试容器-功能-使用方法-注意事项 关键字 Ccbpm, ccflow,jflow,工作流引擎,工作流引擎测试容器,表单引擎 功能说明 工作流的测试容器是为了解决手工模拟人工登录模式下测试 ...

  2. springboot注解之容器功能

    添加组件 @Configuration.@Bean //以swagger为例 @Configuration(proxyBeanMethods = false) @EnableSwagger2 //使用 ...

  3. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法一:使用XML文件定义beans之间的依赖注入关系

    XML-based configuration metadata(使用XML文件定义beans之间的依赖注入关系) 第一部分 编程思路概述 step1,在XML文件中定义各个bean之间的依赖关系. ...

  4. spring cloud: Hystrix(四):feign类似于hystrix的断容器功能:fallback

    spring cloud: Hystrix(四):feign使用hystrix @FeignClient支持回退的概念:fallback方法,这里有点类似于:@HystrixCommand(fallb ...

  5. Spring 系列教程之容器的功能

    Spring 系列教程之容器的功能 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单的了解,在前面的章节中我们一直以 BeanFacotry 接口以及它的默认实现类 XmlBea ...

  6. Spring源码分析(十九)容器的功能扩展概览

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单 ...

  7. 在Linux和Windows的Docker容器中运行ASP.NET Core

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 译者序:其实过去这周我都在研究这方面的内容,结果周末有事没有来得及总结为文章,Scott H ...

  8. Asp.net 面向接口可扩展框架之核心容器(含测试代码下载)

    新框架的容器部分终于调通了!容器实在太重要了,所以有用了一个名词叫“核心容器”. 容器为什么那么重要呢?这个有必要好好说道说道. 1.首先我们从框架名称面向接口编程说起,什么是面向接口编程?(这个度娘 ...

  9. 初识Docker和Windows Server容器

    概览 伴随着Windows Server 2016 Technical Preview 3 (TP3)版本的发布,微软首次提供了Windows平台下地原生容器.它集成了Docker对Windows S ...

  10. Jetty嵌入式Web容器攻略

    Jetty是一个用 Java 实现.开源.基于标准的,并且具有丰富功能的 Http 服务器和 Web 容器.Jetty中应用最广泛的一项功能就是可以作为嵌入式Web容器. 在开发阶段,可以使用Jett ...

随机推荐

  1. linux挂载文件服务器

    smbclient -L //192.168.1.1/ -U administrator //直接挂载 使用下面这条命令就行 sudo mount -t cifs -o username=文件服务器账 ...

  2. spider_object_01使用正则爬取百度贴吧所有内容保存成html

    """本案例不涉及数据提取,仅指导 网页分页爬取的两种方式 思路非第一种:利用while Ture,传参,然后在设定一个判断条件,案例中用的是如果找不到下一页,循环退出( ...

  3. Ajax的两种写法

    先写一串数据 1 { 2 "status": 200, 3 "data": { 4 "name": "web211001" ...

  4. sourceTree工具使用方法

    https://www.cnblogs.com/tian-xie/p/6264104.html

  5. 分布式中间件MyCat 使用

    MySQL 分布式软件MyCAT介绍 目录 MySQL 分布式软件MyCAT介绍 一.MySQL 分布式软件MyCAT介绍 1.1.1 MySQL 分布式软件MyCAT介绍 1.1.2 MyCat 架 ...

  6. std::ref

    The std::thread constructor copies the supplied values, without converting to the expected argument ...

  7. COLMAP论文阅读笔记——sfm算法、不定期更新

    文章目录 structure from motion revisited 第一步 对应点搜索 特征提取feature extraction 匹配matching 几何验证geometric verif ...

  8. js 复制链接内容

    <script type="text/javascript">//复制活动地址 function shareUrl(id) { var url = 'http://H5 ...

  9. 5ppm高精度自动同步标准化考场时钟系统

    自动同步标准化考场时钟系统------专业LED时钟厂家![点击进入]   学校考场医院车站GPS/NTP网络校时之组联网对时精度达5ppm原理剖析.        时间精度是根据各个用户所要求对LE ...

  10. mybatis核心配置文件

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...