Spring的初體驗-1

一. 概述

  1. 官網 https://spring.io/
  2. 核心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
  1. 默認以單例形式管理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對象。

  1. 用戶類直接控制依賴的對象
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();
	}
}

由於用戶類直接控制了依賴的對象,所以用戶類與依賴對象之間就形成了強耦合——改變依賴關係需要修改源代碼。

  1. 使用控制反轉
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)特性才能實現。

  1. 把控制權交給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 + "]";
	}
}
  1. 屬性注入
<?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>
  1. 構造函數注入(通過類型;通過索引;兩者兼用)
通過類型
<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>
  1. 工廠方法注入(非靜態工廠;靜態工廠)
  • 非靜態工廠
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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章