Spring系列12: `@Value` `@Resource` `@PostConstruct` `@PreDestroy` 详解
本文内容
@Resource实现依赖注入@Value详细使用@PostConstruct@PreDestroy的使用
@Resource实现依赖注入
前面章节介绍了使用@Autowired注入依赖的详细用法,感兴趣的可以翻看前面的文章。Spring 还支持通过在字段或 bean 的Setter方法上使用 JSR-250 @Resource 注解进行注入。
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
// 指定名称
String name() default "";
}
基本使用
依赖组件定义
@Component
public class RepositoryA implements RepositoryBase {
}
@Component
public class RepositoryB implements RepositoryBase {
}
使用@Resource注入依赖
@Component
public class Service1 {
// 字段
@Resource
private RepositoryA repositoryA;
private RepositoryB repositoryB;
// Setter方法
@Resource
public void setRepositoryB(RepositoryB repositoryB) {
this.repositoryB = repositoryB;
}
// ...
}
运行测试
@org.junit.Test
public void test() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
Service1 service1 = context.getBean(Service1.class);
System.out.println(service1);
context.close();
}
// 结果
Service1{repositoryA=com.crab.spring.ioc.demo09.RepositoryA@1622f1b, repositoryB=com.crab.spring.ioc.demo09.RepositoryB@72a7c7e0}
@Resource和@Autowired的区别
- 使用范围不同:
@Resource使用范围是类字段和Setter方法,@Autowired范围更广:类字段、Setter方法、构造方法、方法参数。 - 当依赖缺失时,
@Resource注入会报错,@Autowired(required=false)可以避免报错。 @Resource有属性可以指定依赖的bean名称,@Autowired和@Qulifier也可以达到该效果。
@Value详细使用
@Value 通常用于注入外部化属性。在字段或方法构造函数参数级别使用的注释,指示注解元素的默认值表达式。
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
// 实际值表达式如 #{systemProperties.myProp}
// 或属性占位符如${my.app.myProp}
String value();
}
案例1
使用@Value注入配置属性值
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
// ...
}
外部配置文件demo10/application.properties
catalog.name=MovieCatalog
容器中通过@PropertySource配置文件资源
@Configuration
@ComponentScan(basePackages = "com.crab.spring.ioc.demo10")
@PropertySource("classpath:demo10/application.properties")
public class AppConfig {
}
运行测试
@org.junit.Test
public void test() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MovieRecommender recommender = context.getBean(MovieRecommender.class);
System.out.println(recommender);
context.close();
}
// 结果
MovieRecommender{catalog='MovieCatalog'}
从结果看,外部配置文件中的属性值成功注入。
案例2:无法解析属性值
Spring 提供了一个默认的宽松嵌入式值解析器。它将尝试解析属性值,如果无法解析,属性名称(例如 ${catalog.name})将作为值注入。
将配置文件内容修改如下
xxx.catalog.name=MovieCatalog
运行同样上一个案例的测试,可以发现无法解析到属性值则将属性名称注入了。
MovieRecommender{catalog='${catalog.name}'}
如果需要严格控制不存在的值,可以声明一个 PropertySourcesPlaceholderConfigurer并注入到Spring中
@Configuration
@ComponentScan(basePackages = "com.crab.spring.ioc.demo10")
@PropertySource("classpath:demo10/application.properties")
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
运行同样的测试程序,此时严格模式下会抛出异常
java.lang.IllegalArgumentException: Could not resolve placeholder 'catalog.name' in value "${catalog.name}"
扩展: Spring Boot 默认配置一个 PropertySourcesPlaceholderConfigurer bean,它将从 application.properties 和 application.yml 文件中获取属性。
案例3: 提供默认值
可以提供默认值在无法解析属性值作为属性值注入。
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
this.catalog = catalog;
}
}
此时配置文件如下
xxx.catalog.name=MovieCatalog
运行同样的测试程序,注入的是默认值
MovieRecommender{catalog='defaultCatalog'}
案例4:支持SpEL表达式
SpEL表达式后续专门讲,此处不展开。
@PostConstruct @PreDestroy的使用
Spring支持生命周期回调接口注解,@PostConstruct @PreDestroy是JSR 250提供的。
@PostConstruct 注解的方法在容器初始化化bean的阶段回调。
@PostConstruct 注解的方法在容器销毁bean的阶段回调。
直接来看案例
@Component
public class FoodRecommender {
@PostConstruct
public void onInit() {
System.out.println("FoodRecommender onInit");
}
@PreDestroy
public void onDestroy() {
System.out.println("FoodRecommender onDestroy");
}
}
注解的配置相当于下面的xml配置文件
<bean class="com.crab.spring.ioc.demo10.FoodRecommender" id="foodRecommender"
init-method="onInit"
destroy-method="onInit"></bean>
运行下测试程序并观察结果
@org.junit.Test
public void test1() {
System.out.println("开始初始化容器");
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
FoodRecommender bean = context.getBean(FoodRecommender.class);
System.out.println("使用容器中");
System.out.println("销毁容器");
context.close();
}
// 结果
开始初始化容器
FoodRecommender onInit
使用容器中
销毁容器
FoodRecommender onDestroy
总结
本文介绍@Resource实现依赖注入,@Value详细使用和@PostConstruct @PreDestroy的使用。
知识分享,转载请注明出处。学无先后,达者为先!
Spring系列12: `@Value` `@Resource` `@PostConstruct` `@PreDestroy` 详解的更多相关文章
- 精通awk系列(12):awk getline用法详解
回到: Linux系列文章 Shell系列文章 Awk系列文章 getline用法详解 除了可以从标准输入或非选项型参数所指定的文件中读取数据,还可以使用getline从其它各种渠道获取需要处理的数据 ...
- spring的IOC,DI及案例详解
一:spring的基本特征 Spring是一个非常活跃的开源框架:它是一个基于Core来架构多层JavaEE系统的框架,它的主要目的是简化企业开发.Spring以一种非侵入式的方式来管理你的代码,Sp ...
- spring在IoC容器中装配Bean详解
1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean ...
- (转)java之Spring(IOC)注解装配Bean详解
java之Spring(IOC)注解装配Bean详解 在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...
- Spring Boot 启动(二) 配置详解
Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...
- 转载 Spring、Spring MVC、MyBatis整合文件配置详解
Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. ...
- Java 8系列之Stream的基本语法详解
本文转至:https://blog.csdn.net/io_field/article/details/54971761 Stream系列: Java 8系列之Stream的基本语法详解 Java 8 ...
- Python操作redis系列以 哈希(Hash)命令详解(四)
# -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. Hset 命令用于 ...
- SpringBoot系列(六)集成thymeleaf详解版
SpringBoot系列(六)集成thymeleaf详解版 1. thymeleaf简介 1. Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎. 2. Thymeleaf ...
随机推荐
- pytest 一个测试类怎样使用多种fixture前置方法
fixture()方法写在哪里? @pytest.fixture(scope="范围")写在conftest文件中,如下图 怎么使用fixture()呢?分为一个类中使用一个前置或 ...
- Python 使用timeit模块计算时间复杂度时系统报“invalid syntax”错误
最近在看算法相关的文档 在时间复杂度环节 遇到一个实例: 导入timeit模块后,通过Timer定时器计算两种不同处理方法的时间复杂度 错误代码及报错如下图所示: 仔细查阅 发现from__main_ ...
- springMVC+redis+redis自定义工具类 的配置
1. maven项目,加入这一个依赖包即可, <dependency> <groupId>redis.clients</groupId> <artifactI ...
- ubuntu 升级node和npm 版本
使用vue-cli 3 构建项目时会一直卡在拉取依赖不动,原因是node和npm版本过低,升级node版本即可 $ sudo npm cache clean -f $ sudo npm install ...
- Python常用功能函数系列总结(一)
本节目录 常用函数一:获取指定文件夹内所有文件 常用函数二:文件合并 常用函数三:将文件按时间划分 常用函数四:数据去重 写在前面 写代码也有很长时间了,总觉得应该做点什么有价值的事情,写代码初始阶段 ...
- 【分布式技术专题】「Zookeeper中间件」给大家学习一下Zookeeper的”开发伴侣”—Curator-Framework(基础篇)
CuratorFramework基本介绍 CuratorFramework是Netflix公司开源的一套Zookeeper客户端框架,它作为一款优秀的ZooKeeper客户端开源工具,主要提供了对客户 ...
- 从头造轮子:python3 asyncio之 gather (3)
前言 书接上文:,本文造第三个轮子,也是asyncio包里面非常常用的一个函数gather 一.知识准备 ● 相对于前两个函数,gather的使用频率更高,因为它支持多个协程任务"同时&qu ...
- 《剑指offer》面试题53 - II. 0~n-1中缺失的数字
问题描述 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0-n-1之内.在范围0-n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字. 示例 1: 输入: [ ...
- JuiceFS 在理想汽车的使用和展望
理想汽车是中国新能源汽车制造商,设计.研发.制造和销售豪华智能电动汽车,于 2015 年 7 月创立,总部位于北京,已投产的自有生产基地位于江苏常州,通过产品创新及技术研发,为家庭用户提供安全及便捷的 ...
- IDEA包名分层问题
解决办法: 将默认的"Hide empty Middle Packages"或者"compact middle packages"勾选项去掉,这样就不会把中间空 ...