@Autowired、setter、構造函數、beanxml-property、beanxml-constructor-arg 亂七八糟
一、寫在前面
對於標題的這幾個東西想必都不會陌生,但有的時候沒有百分百的拿捏住具體的操作上的區別,雖然,有幾個東西大家用的不多。本文只介紹用法區別。
二、用法介紹
(一)@Autowired
1、概念
(1)其實autowired它是用作裝配(拿spring容器中的現成bean來使用,裝配到當前的類bean中)。
(2)我覺得他是個局部的概念,用一個組件(組件也是個體)組裝成另一個個體,若干個組件的組裝在一起就構成了一個完整的個體。也是一個“過程”的概念。
(3)配置文件xml中的bean呢,跟Java的注解@Bean是一個意思。只是代碼與xml的不同吧。他是一個獨立的個體 + 這個個體如何去組裝別人 或者 由別人組裝。
autowired可以放在任意一個方法前,構造函數,域,Retention.RunTime意味着他的保持時間是運行時保留。
2、用法
(1)放在域前
public class Family {
@Autowired
private Student student;
}
這么寫的意思是,在實例化Family這個類的一個對象時,會從spring容器中拿取一個類型為Student的bean塞到Family的student字段中。
在我看來autowired是一個拿的動作,或者叫使用。
其實把autowired放在域前 《==》 在xml中配置bean,使用setter注入。
(2)放在普通的方法前
@Component
public class ClassB {
@Getter
private ClassA classA;
@Autowired
private void obtainA(ClassA classA) {
this.classA = classA;
}
}
從上面代碼可以看到,其實autowired可以放在任何一個普通的代碼前,除了static,畢竟這個肯定是一個對象,而不是類。
(3)構造函數
@Component
public class ClassB {
@Getter
private ClassA classA;
@Autowired
public ClassB(ClassA classA) {
this.classA = classA;
}
(二)配置文件xml方式配置bean
1、概念
在配置文件里寫bean什么的,很常用,與autowired的區別是,他定義一個個體(bean/類對象), 因此他也取代了@Component等注解的作用。bean的配置里面呢可以是各種組裝(他們完成了autowired的工作)
(1) property 與 setter
//類B
public class ClassB {
@Getter
private ClassA classA;
}
//類A
public class ClassA {
@Getter
private String name = "jenny";
}
//配置文件
<bean id="classB" class="autowired.ClassB">
<property name="classA" ref="classA"/>
</bean>
<bean id="classA" class="autowired.ClassA">
<property name="name" value="jennyA"/>
</bean>
配置文件中,property的意思是會調用你當前類中相應域的setter方法來進行裝配。如果你只是像上面這么寫的話,會報錯:
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'name' of bean class [autowired.ClassA]: Bean property 'name' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
后來,你改為了:
public class ClassB {
@Getter
private ClassA classA;
public void setClassA(ClassA classA) {
this.classA = classA;
}
}
public class ClassA {
@Getter
private String name = "jenny";
public void setName(String name) {
this.name = name;
}
}
這樣就沒有問題了。
所以,從上面兩段代碼可以看出:bean.property + 相應字段的setter方法就可以完成 @Autowired + @Component的工作
(2)constructor-arg + 構造函數
//類B
public class ClassB {
@Getter
private ClassA classA;
public ClassB (ClassA classA) {
this.classA = classA;
}
}
//類A
public class ClassA {
@Getter
private String name = "jenny";
public ClassA(String name) {
this.name = name;
}
}
//配置文件
<bean id="classA" class="autowired.ClassA">
<constructor-arg name="name" value="jennyB"></constructor-arg>
</bean>
<bean id="classB" class="autowired.ClassB">
<constructor-arg name="classA" ref="classA"></constructor-arg>
</bean>
按照配置文件的寫法,那么ClassA與ClassB中一定要有相應的構造函數才行,否則會報錯。
所以,從上可以看出 constructor-arg 的方式可以等價於@Autowired注解。
這么說吧,有了@Autowired了,就取締了property 和 constructor-arg,但是取締不了bean元素,哈哈
(三)autowired與xml.bean的各種混用
隨便寫個例子吧
public class ClassB {
@Getter
private ClassA classA;
@Autowired
//或者放到域classA前也可以,方法前也可以
public ClassB (ClassA classA) {
this.classA = classA;
}
}
<bean id="classA" class="autowired.ClassA">
<constructor-arg name="name" value="jennyB"></constructor-arg>
</bean>
<bean id="classB" class="autowired.ClassB"></bean>
例子中,classB的xml.bean中並沒有寫如何裝配classA,但是在java代碼里寫了進行自動裝配,即從容器里找到這個類型的bean來裝配,classA的bean則寫在了xml文件里。
三、其他問題
1. autowired的幾種裝配方式的區別
2. autowired與構造函數執行的先后順序