浅谈@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 相关文章推荐
解决Maven项目中 Invalid bound statement 无效的绑定问题
Jun 15 Java/Android
深入理解java.lang.String类的不可变性
Jun 27 Java/Android
java解析XML详解
Jul 09 Java/Android
Java中try catch处理异常示例
Dec 06 Java/Android
Netty分布式客户端处理接入事件handle源码解析
Mar 25 Java/Android
springboot入门 之profile设置方式
Apr 04 Java/Android
引用计数法和root搜索算法以及JVM中判定对象需要回收的方法
Apr 19 Java/Android
Ubuntu18.04下QT开发Android无法连接设备问题解决实现
Jun 01 Java/Android
Java界面编程实现界面跳转
Jun 16 Java/Android
SpringBoot详解整合Redis缓存方法
Jul 15 Java/Android
spring boot实现文件上传
Aug 14 Java/Android
Java获取字符串编码格式实现思路
Sep 23 Java/Android
SpringBoot2 参数管理实践之入参出参与校验的方式
Jun 16 #Java/Android
SpringBoot生成License的实现示例
Springboot如何使用logback实现多环境配置?
解决tk mapper 通用mapper的bug问题
一篇带你入门Java垃圾回收器
Java实现简易的分词器功能
Java用自带的Image IO给图片添加水印
You might like
实现分十页分向前十页向后十页的处理
2006/10/09 PHP
20个2014年最优秀的PHP框架回顾
2014/10/22 PHP
基于PHP实现数据分页显示功能
2016/05/26 PHP
php连接微软MSSQL(sql server)完全攻略
2016/11/27 PHP
PHP实现SMTP邮件的发送实例
2018/09/27 PHP
php实现构建排除当前元素的乘积数组方法
2018/10/06 PHP
在页面上点击任一链接时触发一个事件的代码
2007/04/07 Javascript
JS代码放在head和body中的区别分析
2011/12/01 Javascript
jquery 为a标签绑定click事件示例代码
2014/06/23 Javascript
js兼容pc端浏览器并有多种弹出小提示的手机端浮层控件实例
2015/04/29 Javascript
使用JQuery中的trim()方法去掉前后空格
2016/09/16 Javascript
angular基于路由控制ui-router实现系统权限控制
2016/09/27 Javascript
功能强大的jquery.validate表单验证插件
2016/11/07 Javascript
AngularJs中Bootstrap3 datetimepicker使用实例
2016/12/13 Javascript
基于node.js之调试器详解
2017/08/22 Javascript
node.js 核心http模块,起一个服务器,返回一个页面的实例
2017/09/11 Javascript
nodejs结合Socket.IO实现的即时通讯功能详解
2018/01/12 NodeJs
angularjs 获取默认选中的单选按钮的value方法
2018/02/28 Javascript
关于js陀螺仪的理解分析
2019/04/11 Javascript
JavaScript 格式化数字、金额、千分位、保留几位小数、舍入舍去
2019/07/23 Javascript
vue限制输入框只能输入8位整数和2位小数的代码
2019/11/06 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
2020/05/11 Javascript
Vue单文件组件开发实现过程详解
2020/07/30 Javascript
element中table高度自适应的实现
2020/10/21 Javascript
原生js实现简单轮播图
2020/10/26 Javascript
Python使用sorted排序的方法小结
2017/07/28 Python
django创建超级用户时指定添加其它字段方式
2020/05/14 Python
Python经纬度坐标转换为距离及角度的实现
2020/11/01 Python
PHP笔试题
2012/02/22 面试题
康拓普公司Java笔面试
2016/09/23 面试题
《两个铁球同时着地》教学反思
2014/02/13 职场文书
开票员岗位职责
2015/02/12 职场文书
2015暑期社会实践通讯稿
2015/07/18 职场文书
2015年幼儿园国庆节活动总结
2015/07/30 职场文书
导游词之云南-元阳梯田
2019/10/08 职场文书
Apache POI的基本使用详解
2021/11/07 Servers