博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring枚举变量的注入&构造函数
阅读量:6152 次
发布时间:2019-06-21

本文共 2044 字,大约阅读时间需要 6 分钟。

hot3.png

public enum EventType {    IP_CHANGE,REGISTER_SERVER}   @Data    static public class Entry{        private EventType eventType;        private CopyOnWriteArrayList
listeners; public Entry(EventType eventType){ this.eventType = eventType; this.listeners = new CopyOnWriteArrayList<>(); } //public Entry(){ //} }

想使用Spring 构建一个bean id="IP_CHANGE_ENTRY"的Entry对象,但是EventType是枚举类型,所以必须使用

org.springframework.beans.factory.config.FieldRetrievingFactoryBean实现枚举类型的注入,将EventType.IP_CHANGE放入静态字段即可。

9a41aad8-48b6-4ab4-9650-90b473b128c6.png

为什么是静态字段呢,因为Java枚举型是静态常量,隐式地用static final修饰过,使用CRFjava -jar cfr_0_124.jar EventType.class --sugarenums false反编译结果如下:

d14948b2-2956-45e2-b377-fee3ad34d0e6.png

当静态字段注册完成后,运行会报错

74bc5509-d887-4ea8-a29e-6d1909180a40.png

从错误里看是因为存在两个EventType,在Entry构造函数中注入EventType时,Spring不知道注入谁。解决方法有二种,第一种:

48bf3a00-8e96-4294-808d-f39c91632d21.png

为什么要必须要添加默认无参构造函数呢,源码关键在

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

2cf9dd40-b09a-4256-89f9-114af4b50139.png

f438901c-aca0-4f73-8dbb-f41d0a7cb2a2.png

de6e7a97-cda4-4ca5-8ae3-77bff8ea7a07.png

这里是返回candidateConstructors 还是null会影响到下面的走势,如果是null,直接进入instantiateBean,反之,进入autowireConstructor,一旦进入这个,会存在缺少primary导致的无法决策哪一个bean的问题。

85269442-bbb5-4186-bd21-7dcc40ef3fb6.png

第二种:使用primary=true来告诉Spring优先使用这个Bean,默认是false,解释:Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.

当一个类有多个bean时,添加primary=true表示该bean优先于其他bean被注入

2b8a47b3-face-4e0c-b1a2-d4ce833dd91a.png

下面分析与primary相关的源码

org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

4489787e-8671-4635-ba6e-8c2479f884c6.png

进入org.springframework.beans.factory.support.DefaultListableBeanFactory#determineAutowireCandidate

在选择自动注入的bean时,有2个选择依据,分别是primary & priority。如果IP_CHANGE_TYPE设置了primary,则primaryCandidate会被设置为IP_CHANGE_TYPE,并作为被注入者返回

800afa31-7675-4333-8d4c-b75200a2d10d.png

如果bean中定义了primary,例如

<bean id = "IP_CHANGE_TYPE" primary="true" class="..."/>,则该方法会返回true,会执行到primaryName=candidateBeanName,primaryName被赋值为IP_CHANGE_TYPE

38beaca4-08e4-4f90-8063-eadd9de85684.png

getMergedLocalBeanDefition会返回一个REGISTER_SERVER_TYPE的AbstractBeanDefition对象,该对象描述了xml中REGISTER_SERVER_TYPE bean的定义规则,该bean没有定义primary,默认为false,所以isPrimary()返回的是false

62aaaf46-2b3f-46e4-9e1d-86d7626029f1.png

08eaab29-8ed9-47a7-9260-3390a8f0da21.png

转载于:https://my.oschina.net/u/2302503/blog/1859093

你可能感兴趣的文章
SQL Server表分区详解
查看>>
使用FMDB最新v2.3版本教程
查看>>
SSIS从理论到实战,再到应用(3)----SSIS包的变量,约束,常用容器
查看>>
STM32启动过程--启动文件--分析
查看>>
垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
查看>>
淘宝的几个架构图
查看>>
Android扩展 - 拍照篇(Camera)
查看>>
数据加密插件
查看>>
linux后台运行程序
查看>>
win7 vs2012/2013 编译boost 1.55
查看>>
Tar打包、压缩与解压缩到指定目录的方法
查看>>
配置spring上下文
查看>>
Python异步IO --- 轻松管理10k+并发连接
查看>>
Oracle中drop user和drop user cascade的区别
查看>>
登记申请汇总
查看>>
Android Jni调用浅述
查看>>
CodeCombat森林关卡Python代码
查看>>
第一个应用程序HelloWorld
查看>>
(二)Spring Boot 起步入门(翻译自Spring Boot官方教程文档)1.5.9.RELEASE
查看>>
Java并发编程73道面试题及答案
查看>>