浅谈@Value和@Bean的执行顺序问题


Posted in Java/Android onJune 16, 2021

问题描述

使用@Autowired处理多个同种类型的bean,出现@Value和@Bean的执行顺序问题。

首先使用扫描包+注解的方式注册User类型的不同bean,分别是user、user1,注册方式如下

package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    private Integer id;
    private String name;
}

该方式得到User类型的名为user的bean

package com.fanyinhang.config;
import com.fanyinhang.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value={"com.fanyinhang.dao"})
public class AnnotationConfig {
    @Bean()
    public User user1(){
        return new User(2,"李四");
    }
}

UserDao配置如下:

package com.fanyinhang.dao;
import com.fanyinhang.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:17
 */
@Repository
public class UserDao {
    @Autowired()
    private User user1;
    
    @Override
    public String toString() {
        return "UserDao{" +
                "user1=" + user1 +
                '}';
    }
}
import com.fanyinhang.config.AnnotationConfig;
import com.fanyinhang.dao.UserDao;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:18
 */
public class Test3 {
    @Test
    public void testAutowired(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationConfig.class);
        UserDao userDao = context.getBean(UserDao.class);
        System.out.println(userDao);
    }
}

输出结果如下:

UserDao{user1=User(id=2, name=李四)}

没有加入@Value注解时是没有问题的,但是加入了@Value之后

package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    @Value("1")
    private Integer id;
    @Value("张三")
    private String name;
}

再次运行testWired方法后

结果输出如下:

UserDao{user1=User(id=1, name=张三)}

为什么会出现这种情况?

一开始,怎么也想不通,查看网上的资料大多数是说@Bean和@Value有执行顺序这一说法。

为了验证这一说法,做个对比试验

去掉了一个@Value(“张三”)

package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    @Value("1")
    private Integer id;
    //@Value("张三")
    private String name;
}

结果输出如下:

UserDao{user1=User(id=1, name=李四)}

问题原因

@Value和@Bean在不同文件下时,@Bean比@Value先执行。这样就回导致@Bean注入的值失效。

解决办法

网上说@Value和@Bean在不同文件下时,@Value比@Bean先执行,因此,我做了如下设置

把User.java下的@Value注解去掉,而是将@Value注解放在@bean同一文件下

package com.fanyinhang.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
/**
 * @author fanyinhang
 * @version 1.0
 * @create 2019/10/8-19:11
 */
@NoArgsConstructor
@Data
@AllArgsConstructor
@Component
public class User {
    private Integer id;
    private String name;
}
package com.fanyinhang.config;
import com.fanyinhang.bean.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value={"com.fanyinhang.dao"})
public class AnnotationConfig {
    @Bean()
    public User user1(@Value("1") Integer id,@Value("张三") String name){
        return new User(2,"李四");
    }
}

此时再运行测试方式,输出结果如下:

UserDao{user1=User(id=2, name=李四)}

总结

以上为个人经验,希望能给大家一个参考,有什么理解不到位的地方,请大家多多指正,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
详解Java实践之建造者模式
Jun 18 Java/Android
Spring Boot 整合 Apache Dubbo的示例代码
Jul 04 Java/Android
看完这篇文章获得一些java if优化技巧
Jul 15 Java/Android
JVM钩子函数的使用场景详解
Aug 23 Java/Android
spring cloud eureka 服务启动失败的原因分析及解决方法
Mar 17 Java/Android
使用HttpSessionListener监听器实战
Mar 17 Java/Android
java如何实现获取客户端ip地址的示例代码
Apr 07 Java/Android
Java虚拟机内存结构及编码实战分享
Apr 07 Java/Android
java中为什么说子类的构造方法默认访问的是父类的无参构造方法
Apr 13 Java/Android
Spring Data JPA框架持久化存储数据到数据库
Apr 28 Java/Android
httpclient调用远程接口的方法
Aug 14 Java/Android
OpenFeign实现远程调用
Aug 14 Java/Android
SpringBoot2 参数管理实践之入参出参与校验的方式
Jun 16 #Java/Android
SpringBoot生成License的实现示例
Springboot如何使用logback实现多环境配置?
解决tk mapper 通用mapper的bug问题
一篇带你入门Java垃圾回收器
Java实现简易的分词器功能
Java用自带的Image IO给图片添加水印
You might like
PHPEXCEL 使用小记
2013/01/06 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
PHP实现分布式memcache设置web集群session同步的方法
2018/04/10 PHP
js调用css属性写法
2013/09/21 Javascript
js实现TAB切换对应不同颜色的代码
2015/08/31 Javascript
jQuery实现每隔几条元素增加1条线的方法
2016/06/27 Javascript
BootStrap 导航条实例代码
2017/05/18 Javascript
bootstrap fileinput实现文件上传功能
2017/08/23 Javascript
js实现canvas保存图片为png格式并下载到本地的方法
2017/08/31 Javascript
细说webpack源码之compile流程-rules参数处理技巧(1)
2017/12/26 Javascript
移动web开发之touch事件实例详解
2018/01/17 Javascript
node.js自动上传ftp的脚本分享
2018/06/16 Javascript
Vue.js的动态组件模板的实现
2018/11/26 Javascript
移动端自适应flexible.js的使用方法(不用三大框架,仅写一个单html页面使用)推荐
2019/04/02 Javascript
[02:57]DOTA2英雄基础教程 风行者
2014/01/16 DOTA
python线程池(threadpool)模块使用笔记详解
2017/11/17 Python
Python实现的HMacMD5加密算法示例
2018/04/03 Python
Numpy数据类型转换astype,dtype的方法
2018/06/09 Python
Python使用win32com模块实现数据库表结构自动生成word表格的方法
2018/07/17 Python
使用tensorflow实现线性回归
2018/09/08 Python
Python3编码问题 Unicode utf-8 bytes互转方法
2018/10/26 Python
Python线程池模块ThreadPoolExecutor用法分析
2018/12/28 Python
使用python实现抓取腾讯视频所有电影的爬虫
2019/04/15 Python
Django 路由控制的实现
2019/07/17 Python
python中shell执行知识点
2020/05/06 Python
基于Python爬取京东双十一商品价格曲线
2020/10/23 Python
Python+unittest+requests+excel实现接口自动化测试框架
2020/12/23 Python
html5 canvas的绘制文本自动换行的示例代码
2018/09/17 HTML / CSS
使用layui实现左侧菜单栏及动态操作tab项的方法
2020/11/10 HTML / CSS
泰国办公用品购物网站:OfficeMate
2018/02/04 全球购物
Fnac西班牙官网:法国文化和电子产品零售商
2021/03/14 全球购物
2014全国两会大学生学习心得体会
2014/03/10 职场文书
病媒生物防治方案
2014/05/13 职场文书
庆祝新中国成立65周年“向国旗敬礼”网上签名寄语
2014/09/27 职场文书
让子弹飞观后感
2015/06/11 职场文书