一. 概述
- 官網 https://spring.io/
- 核心jar包
commons-collections-3.2.jar
commons-logging.jar
spring-aop-4.0.6.RELEASE.jar
spring-beans-4.0.6.RELEASE.jar
spring-context-4.0.6.RELEASE.jar
spring-core-4.0.6.RELEASE.jar
spring-expression-4.0.6.RELEASE.jar
- 默認以單例形式管理bean
- src/beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloWorld" class="com.bee.HelloWorld"></bean>
</beans>
被管理的類
public class HelloWorld {
public void say(){
System.out.println("Spring4俺來也");
}
}
測試類
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bee.HelloWorld;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
HelloWorld helloWorld=(HelloWorld)ac.getBean("helloWorld");
helloWorld.say();
}
}
這樣就可以讓Spring來管理bean。
二. Spring IoC
IoC(控制反轉:Inverse of Control),用於解除類之間的耦合,他是Spring架構的核心。IoC體現的是設計模式中的“好萊塢法則:don’t call us, we’ll call you”。
這裏的“控制”就是new
對象。在哪個類中new對象,那個類就控制被new的對象。控制反轉就是要取消類中的new,把所有獲得對象的new都統一收歸到Spring框架裏來,比如:
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
這樣就只有一個new,用於生成Spring框架的對象。Spring框架就可以統一管理各個對象,而不是讓用戶的類來管理對象。用戶對類對象的控制權就反轉過來交給Spring框架——控制反轉。
現在設定一個場景用於解釋控制反轉:
項目主管Boss安排測試人員Mufasa和Daoba對代碼進行測試。用戶類是Boss,而類Mufasa和Daoba受Boss管理,Boss類依賴Mufasa和Daoba對象。
- 用戶類直接控制依賴的對象
public class Mufasa {
public void doTest() {
System.out.println("我不入地獄誰入地獄,一個字——幹。");
}
}
public class Daoba {
public void doTest() {
System.out.println("王侯將相寧有種乎,老子就不幹,咋地。");
}
}
//Boss類與Mufasa和Daoba對象深度耦合——如果Boss不想要Daoba,還得修改自身的代碼再編譯。
public class Boss {
public void comeOnBaby() {
Mufasa mufasa = new Mufasa();
mufasa.doTest();
Daoba daoba = new Daoba();
daoba.doTest();
}
}
//測試
public class ClientGo {
public static void main(String[] args) {
Boss boss = new Boss();
boss.comeOnBaby();
}
}
由於用戶類直接控制了依賴的對象,所以用戶類與依賴對象之間就形成了強耦合——改變依賴關係需要修改源代碼。
- 使用控制反轉
public interface Tester {
void doTest();
}
public class Mufasa implements Tester {
@Override
public void doTest() {
System.out.println("我不入地獄誰入地獄,一個字——幹。");
}
}
public class Daoba implements Tester {
@Override
public void doTest() {
System.out.println("王侯將相寧有種乎,老子就不幹,咋地。");
}
}
public class Boss {
private Tester tester;
//這裏就是Boss的依賴注入(DI)
public void setTester(Tester tester) {
this.tester = tester;
}
public void comeOnBaby() {
tester.doTest();
}
}
//測試
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bee.beans.Boss;
public class ClientGo {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");
Boss boss = (Boss) appContext.getBean("boss");
boss.comeOnBaby();
}
}
控制反轉的實現需要藉助依賴注入(DI,Dependency Injection)特性才能實現。
- 把控制權交給Spring框架
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mufasa" class="com.bee.beans.Mufasa"></bean>
<bean id="daoba" class="com.bee.beans.Daoba"></bean>
<bean id="boss" class="com.bee.beans.Boss">
<property name="tester" ref="mufasa"></property>
</bean>
</beans>
對依賴對象的管理變成Spring框架配置文件中一個bean標籤的管理。在配置文件中還可以通過property標籤來管理依賴注入——這裏Boss方便地完成了對Mufasa的依賴,而剔除了對Daoba的依賴——不用修改自身源代碼。
這一切的實現基礎是反射。值得關注的是控制反轉後看不到用戶類的new操作了。
三. Spring DI的常見方式
先定義一個實體bean
public class People {
private int id;
private String name;
private int age;
public People() {
super();
}
public People(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
- 屬性注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="people" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="穆法沙"></property>
<property name="age" value="8"></property>
</bean>
</beans>
- 構造函數注入(通過類型;通過索引;兩者兼用)
通過類型
<bean id="people" class="com.bee.entity.People">
<constructor-arg type="int" value="2"></constructor-arg>
<constructor-arg type="String" value="辛巴"></constructor-arg>
<constructor-arg type="int" value="6"></constructor-arg>
</bean>
通過索引
<bean id="people" class="com.bee.entity.People">
<constructor-arg index="0" value="2"></constructor-arg>
<constructor-arg index="1" value="辛巴"></constructor-arg>
<constructor-arg index="2" value="6"></constructor-arg>
</bean>
兩者兼用
<bean id="people" class="com.bee.entity.People">
<constructor-arg index="0" type="int" value="2"></constructor-arg>
<constructor-arg index="1" type="String" value="辛巴"></constructor-arg>
<constructor-arg index="2" type="int" value="6"></constructor-arg>
</bean>
- 工廠方法注入(非靜態工廠;靜態工廠)
- 非靜態工廠
public class PeopleFactory {
public People createPeople(){
People p=new People();
p.setId(3);
p.setName("刀疤");
p.setAge(10);
return p;
}
}
配置文件beans.xml
<bean id="peopleFactory" class="com.bee.factory.PeopleFactory"></bean>
<bean id="people" factory-bean="peopleFactory" factory-method="createPeople"></bean>
- 靜態工廠
public class PeopleFactory {
public static People createPeople(){
return new People(4, "波波", 8);
}
}
配置文件beans.xml(靜態方法是跟着類class走的)
<bean id="peopleFactory" class="com.bee.factory.PeopleFactory"></bean>
<bean id="people" class="com.bee.factory.PeopleFactory" factory-method="createPeople"></bean>
四. Spring注入參數
實體bean
public class People {
private int id;
private String name;
private int age;
private Dog dog;
private List<String> hobbies=new ArrayList<String>();
private Set<String> loves=new HashSet<String>();
private Map<String,String> works=new HashMap<String,String>();
private Properties addresses=new Properties();
public People() {
}
public People(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Set<String> getLoves() {
return loves;
}
public void setLoves(Set<String> loves) {
this.loves = loves;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public Map<String, String> getWorks() {
return works;
}
public void setWorks(Map<String, String> works) {
this.works = works;
}
public Properties getAddresses() {
return addresses;
}
public void setAddresses(Properties addresses) {
this.addresses = addresses;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", age=" + age
+ ", dog=" + dog + ", hobbies=" + hobbies + ", loves=" + loves
+ ", works=" + works + ", addresses=" + addresses + "]";
}
}
public class Dog {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
參數注入的例子
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
1. 基本類型值
<bean id="people1" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="張三"></property>
<property name="age" value="11"></property>
</bean>
<bean id="dog1" class="com.bee.entity.Dog">
<property name="name" value="Jack"></property>
</bean>
2. 注入bean
<bean id="people2" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="張三"></property>
<property name="age" value="11"></property>
<property name="dog" ref="dog1"></property>
</bean>
3. 內部bean
<bean id="people3" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="張三"></property>
<property name="age" value="11"></property>
<property name="dog">
<bean class="com.bee.entity.Dog">
<property name="name" value="Tom"></property>
</bean>
</property>
</bean>
4. null值
<bean id="people4" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="張三"></property>
<property name="age" value="11"></property>
<property name="dog">
<null></null>
</property>
</bean>
5. 級聯屬性
<bean id="people5" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="張三"></property>
<property name="age" value="11"></property>
<property name="dog.name" value="Jack2"></property>
</bean>
6. 集合類型屬性
<bean id="people6" class="com.bee.entity.People">
<property name="id" value="1"></property>
<property name="name" value="張三"></property>
<property name="age" value="11"></property>
<property name="dog" ref="dog1"></property>
<property name="hobbies">
<list>
<value>唱歌</value>
<value>跳舞</value>
</list>
</property>
<property name="loves">
<set>
<value>唱歌2</value>
<value>跳舞2</value>
</set>
</property>
<property name="works">
<map>
<entry>
<key><value>上午</value></key>
<value>寫代碼</value>
</entry>
<entry>
<key><value>下午</value></key>
<value>測試代碼</value>
</entry>
</map>
</property>
<property name="addresses">
<props>
<prop key="address1">aaaaa</prop>
<prop key="address2">bbbbb</prop>
</props>
</property>
</bean>
</beans>