public enum EventType { IP_CHANGE,REGISTER_SERVER } @Data static public class Entry{ private EventType eventType; private CopyOnWriteArrayList<EventListener> listeners; public Entry(EventType eventType){ this.eventType = eventType; this.listeners = new CopyOnWriteArrayList<>(); } //public Entry(){ //} }
想使用Spring 構建一個bean id="IP_CHANGE_ENTRY"的Entry對象,可是EventType是枚舉類型,因此必須使用java
org.springframework.beans.factory.config.FieldRetrievingFactoryBean實現枚舉類型的注入,將EventType.IP_CHANGE放入靜態字段便可。spring
爲何是靜態字段呢,由於Java枚舉型是靜態常量,隱式地用static final修飾過,使用CRF(java -jar cfr_0_124.jar EventType.class --sugarenums false)反編譯結果以下:函數
當靜態字段註冊完成後,運行會報錯this
從錯誤裏看是由於存在兩個EventType,在Entry構造函數中注入EventType時,Spring不知道注入誰。解決方法有二種,第一種:3d
爲何要必需要添加默認無參構造函數呢,源碼關鍵在code
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructorsxml
這裏是返回candidateConstructors 仍是null會影響到下面的走勢,若是是null,直接進入instantiateBean,反之,進入autowireConstructor,一旦進入這個,會存在缺乏primary致使的沒法決策哪個bean的問題。對象
第二種:使用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.blog
當一個類有多個bean時,添加primary=true表示該bean優先於其餘bean被注入ip
下面分析與primary相關的源碼
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
進入org.springframework.beans.factory.support.DefaultListableBeanFactory#determineAutowireCandidate
在選擇自動注入的bean時,有2個選擇依據,分別是primary & priority。若是IP_CHANGE_TYPE設置了primary,則primaryCandidate會被設置爲IP_CHANGE_TYPE,並做爲被注入者返回
若是bean中定義了primary,例如
<bean id = "IP_CHANGE_TYPE" primary="true" class="..."/>,則該方法會返回true,會執行到primaryName=candidateBeanName,primaryName被賦值爲IP_CHANGE_TYPE
getMergedLocalBeanDefition會返回一個REGISTER_SERVER_TYPE的AbstractBeanDefition對象,該對象描述了xml中REGISTER_SERVER_TYPE bean的定義規則,該bean沒有定義primary,默認爲false,因此isPrimary()返回的是false