SSM框架(Spring + SpringMVC + MyBatis)學習筆記,第一課:Spring IoC

  1. Spring框架概述圖
    這張圖展示了,搭建項目時所需要的模塊(對應的jar包),例如:使用spring框架連接數據庫,則需要用到Core, Aop, Dao模塊的jar包。
    Spring框架概述

  2. 下載使用eclipse搭建ssm框架(Spring + SpringMVC + MyBatis)所需要的jar包。這個jar包只能支持1.7及以下版本的JDK,若使用了高版本的JDK,需要去spring官網去下載jar包

    解壓之後獲得
    在這裏插入圖片描述
    本章主要介紹SpringIoC,所以只使用其中的ioc文件夾下的jar包和applicationContext.xml文件
    在這裏插入圖片描述
    在這裏插入圖片描述

  3. 創建web project
    打開eclipse,選擇File >>> New >>> Dynamic Web Project
    在這裏插入圖片描述
    在這裏插入圖片描述
    在這裏插入圖片描述
    填寫完項目名稱之後,直接點擊Finish,項目就創建完成了。
    創建之後的目錄結構如下:
    在這裏插入圖片描述

  4. 打開下載的jar包,將ioc文件夾下的jar包複製到lib目錄下,將applicationContext.xml文件複製到src目錄下
    在這裏插入圖片描述
    到此,環境已經準備完成。

  5. 使用SpringIoC創建對象的三種方法
    src目錄下創建一個class文件,用於接下來的測試
    在這裏插入圖片描述
    第一種方法:採用new構造器創建對象
    不使用框架

package org.springioc.test;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class TestBean {

	public static void main(String[] args) {
		Calendar c1 = new GregorianCalendar();
		System.out.println("c1="+c1);

	}
	
}

使用框架
首先在applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util"  
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

<!-- 使用new構造器方法創建對象 -->
<bean id="c2" class="java.util.GregorianCalendar"></bean>

</beans>

然後在測試類TestBean中通過框架創建對象

package org.springioc.test;

import java.util.Calendar;
import java.util.GregorianCalendar;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBean {

	public static void main(String[] args) {
		Calendar c1 = new GregorianCalendar();
		System.out.println("c1="+c1);
		
		String conf = "applicationContext.xml";//配置文件的文件名
		//實例化容器
		ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
		//創建對象,
		//ac.getBean("c2", Calendar.class)
		//c2爲配置文件applicationContext.xml中的id
		//Calendar.class爲獲取對象的類型
		Calendar c2222 = ac.getBean("c2", Calendar.class);
		System.out.println("c2222="+c2222);

	}
	
}

第二種方法:採用靜態工廠方法創建對象
不使用框架
測試類TestBean

Calendar c3 = Calendar.getInstance();

使用框架
首先在applicationContext.xml中增加配置

<!-- 使用靜態工廠方法創建對象 -->
<bean id="c3" class="java.util.Calendar" factory-method="getInstance"></bean>

測試類TestBean

Calendar c3333 = ac.getBean("c3", Calendar.class);
System.out.println("c3333="+c3333);

第三中方法:採用對象工廠方法創建對象
不使用框架
測試類TestBean

Date date = c3.getTime();
System.out.println("date="+date);

使用框架
首先在applicationContext.xml中增加配置,c3爲第二種方法種配置的id

<!-- 採用對象工廠方法創建對象 -->
<bean id="date" factory-bean="c3" factory-method="getTime"></bean>

測試類TestBean

Date date3333 = ac.getBean("date", Date.class);
System.out.println("date3333="+date3333);
  1. 創建對象時單例,非單例控制
    使用以上方式創建對象,默認是單例(singleton),但是可以通過scope屬性 更改,它的值有singleton(單例)和prototype(非單例)。
    下面舉例說明:
    src目錄下新建目錄org.spingioc.bean,在此目錄下新建類ExampleBean
package org.springioc.bean;

public class ExampleBean {

	public void execute() {
		System.out.println("調用execute方法");
	}

}

使用框架,創建對象
首先配置applicationContext.xml

<bean id="e1" class="org.springioc.bean.ExampleBean"></bean>

編寫測試類ExampleTest

package org.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springioc.bean.ExampleBean;

public class ExampleTest {

	public static void main(String[] args) {
		String conf ="applicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
		ExampleBean e1 = ac.getBean("e1", ExampleBean.class);
		ExampleBean e2 = ac.getBean("e1", ExampleBean.class);
		System.out.println(e1==e2);
	}

}

結果爲true,代表爲singleton模式。
applicationContext.xml增加scope屬性,將它改爲非單例模式

<bean scope="prototype" id="e1" class="org.springioc.bean.ExampleBean"></bean>

再次運行測試類ExampleTest,結果爲false,代表爲非單例模式。

  1. 創建對象時初始化動作
    不使用框架,可以使用構造器構造代碼塊實現對象的初始化
package org.springioc.bean;

public class ExampleBean {
	
	{
		System.out.println("構造代碼塊!");
	}
	
	public ExampleBean() {
		System.out.println("無參構造函數!");
	}
	
	public void execute() {
		System.out.println("調用execute方法");
	}

}

運行測試類ExampleTest,控制檯顯示
在這裏插入圖片描述
使用框架
首先在ExampleBean類中增加初始化函數init

	public void init() {
		System.out.println("初始化方法!");
	}

init函數配置在applicationContext.xml

<bean init-method="init" scope="prototype" id="e1" class="org.springioc.bean.ExampleBean"></bean>

運行測試類ExampleTest,控制檯顯示
在這裏插入圖片描述
以上這兩種方法初始化對象的區別,使用構造代碼塊構造器初始化對象,是在對象創建的過程中初始化對象,使用init-method初始化對象,是在對象創建完成再對對象做初始化動作。

  1. 對象的銷燬
    applicationContext.xml中配置destroy-method實現對象的銷燬。使用bean中的這個屬性,需要兩個條件支持
    第一個:必須實現AbstractApplicationContext容器,並且運行它的close方法
package org.springioc.test;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ExampleTest {

	public static void main(String[] args) {
		String conf ="applicationContext.xml";
		AbstractApplicationContext ac = new ClassPathXmlApplicationContext(conf);
		ac.close();
	}
}

第二個:對象必須是單例模式(singleton

<bean destroy-method="destroy"  init-method="init" scope="singleton" id="e1" class="org.springioc.bean.ExampleBean"></bean>

另外在ExampelBean中增加destroy方法

public void destroy() {
		System.out.println("銷燬對象!");
	}

運行ExampleTest類,
在這裏插入圖片描述

  1. 控制單例對象的創建時機
    若需在實例化容器的時候創建對象,需要在applicationContext.xml配置三個屬性
    第一個:abstract=“false”,不配置默認爲false
    第二個:scope=“singleton” ,不配默認爲singleton
    第三個:lazy-init="false"
<bean abstract="false" lazy-init="false" destroy-method="destroy" init-method="init" scope="singleton" id="e1" class="org.springioc.bean.ExampleBean"></bean>

否則在調用容器的getBean函數的時候創建對象

<bean abstract="false" lazy-init="true" destroy-method="destroy" init-method="init" scope="singleton" id="e1" class="org.springioc.bean.ExampleBean"></bean>
  1. applicationContext.xmlbean元素中配置的init-method, destroy-method, lazy-init是針對單個對象的;也可以在beans元素中配置default-init-method, default-destroy-method, default-lazy-init,這樣對配置文件中的每一個對象都能生效。(瞭解)

  2. SpringIoC依賴注入(控制反轉或反向控制)
    控制反轉:改變了獲取對象的方式,不使用框架的情況下,使用new創建對象;ioc中,由容器創建對象,對象的參數,以及對象之間的關係,只需要修改配置即可改變。
    下面介紹兩種方式:
    第一種,構造器注入,這種方法需要創建有參的構造器
    首先創建一個Phone

package org.springioc.bean;

public class Phone {
	private String brand;
	private String price;
	
	public Phone(String brand, String price) {
		this.brand=brand;
		this.price=price;
	}
	
	public void show() {
		System.out.println("--手機--brand:"+brand+" price:"+price);
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public void setPrice(String price) {
		this.price = price;
	}
	
}

配置applicationContext.xml文件

<bean id="p1" class="org.springioc.bean.Phone">
	<!-- 構造器注入,index參數序號從零開始計數,value想要賦給對象屬性的值 -->
	<constructor-arg index="0" value="蘋果"></constructor-arg>
	<constructor-arg index="1" value="12000"></constructor-arg>
</bean>

編寫測試類PhoneTest

package org.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springioc.bean.Phone;

public class PhoneTest {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Phone p = ac.getBean("p1", Phone.class);
		p.show();
	}
	
}

第二種:set注入
創建Computer

package org.springioc.bean;

public class Computer {
	private String brand;
	private String price;
	
	public void show() {
		System.out.println("--電腦--brand:"+brand+" price:"+price);
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public void setPrice(String price) {
		this.price = price;
	}
	
}

配置applicationContext.xml文件

<bean id="pc" class="org.springioc.bean.Computer">
	<!-- set注入,name對象屬性,value屬性值 -->
	<property name="brand" value="聯想"></property>
	<property name="price" value="8000"></property>
</bean>

編寫測試類PhoneTest

package org.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springioc.bean.Phone;

public class PhoneTest {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Phone p = ac.getBean("p1", Phone.class);
		p.show();
	}
	
}

另一種情況如果屬性值爲一個對象,該如何用注入的方式
創建Student

package org.springioc.bean;

public class Student {
	private Phone phone;
	private Computer pc;
	
	public void show() {
		phone.show();
		pc.show();
	}

	public void setPhone(Phone phone) {
		this.phone = phone;
	}

	public void setPc(Computer pc) {
		this.pc = pc;
	}
	
}

配置applicationContext.xml文件,使用ref引用原有的對象

<bean id="st" class="org.springioc.bean.Student">
	<property name="phone" ref="p1"></property>
	<property name="pc" ref="pc"></property>
</bean>

編寫測試類StudentTest

package org.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springioc.bean.Student;

public class StudentTest {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Student st = ac.getBean("st", Student.class);
		st.show();
	}

}
  1. 自動注入(autowrite),瞭解就可!
    Spring IoC容器可以自動裝配(autowire)相互協作bean之間的關聯關係。因此,如果可能的話,可以自動讓Spring通過檢查BeanFactory中的內容,來替我們指定bean的協作者(其他被依賴的bean)。autowire一共有五種類型(“no”, “byName”, “byType”, “constructor”, “autodetect”)。由於autowire可以針對單個bean進行設置,因此可以讓有些bean使用autowire,有些bean不採用。autowire的方便之處在減少或者消除屬性或構造器參數的設置,這樣可以給我們的配置文件減減肥!
    下面以"byType"舉例:
    配置applicationContext.xml文件
<bean id="st1" class="org.springioc.bean.Student" autowire="byType"></bean>

修改測試類StudentTest

package org.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springioc.bean.Student;

public class StudentTest {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Student st = ac.getBean("st1", Student.class);
		st.show();
	}
}
  1. 各種類型的信息注入配置
    創建類MessageBean
package org.springioc.bean;

import java.sql.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;

public class MessageBean {
	private String name;
	private int age;
	private Date birth;
	private List<String> friends;
	private Set<String> cities;
	private Map<String,String> books;
	private Properties db;
	
	public void show() {
		String lstFriends="";
		for(int i=0;i<friends.size();i++) {
			lstFriends +=friends.get(i)+",";
		}
		System.out.println("name:"+name+", age:"+age+", birth:"+birth+", friends:"+lstFriends);
		
		for(String s : cities) {
			System.out.println(s);
		}
		
		Set<Entry<String,String>> booksSet = books.entrySet();
		for(Entry<String,String> e :booksSet) {
			System.out.println("key:"+e.getKey()+", value:"+e.getValue());
		}
		
		Set<Object> dbSet = db.keySet();
		for(Object key : dbSet) {
			System.out.println("key:"+key+", value:"+db.getProperty(key.toString()));
		}
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public void setBirth(String birth) {
		Date date =Date.valueOf(birth);
		this.birth = date;
	}

	public void setFriends(List<String> friends) {
		this.friends = friends;
	}

	public void setCities(Set<String> cities) {
		this.cities = cities;
	}

	public void setBooks(Map<String, String> books) {
		this.books = books;
	}

	public void setDb(Properties db) {
		this.db = db;
	}
	
}

第一,基礎類型,和String類型

	<!-- 給name賦值null -->
	<property name="name">
		<null/>
	</property>
	<property name="age" value="18"></property>
	<!-- birth爲Date類型,set方法需要重寫 -->
	<property name="birth" value="2019-01-01"></property>

第二,List類型

	<property name="friends">
		<list>
			<value>朋友1</value>
			<value>朋友2</value>
		</list>
	</property>

第三,Set類型

	<property name="cities">
		<set>
			<value>城市1</value>
			<value>城市2</value>
		</set>
	</property>

第四,Map類型

	<property name="books">
		<map>
			<entry key="001" value="書1"></entry>
			<entry key="002" value="書2"></entry>
		</map>
	</property>

第五,Properties類型

	<property name="db">
		<props>
			<prop key="username">root</prop>
			<prop key="password">123456</prop>
		</props>
	</property>

編寫測試類MessageTest

package org.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springioc.bean.MessageBean;

public class MessageTest {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		MessageBean msg = ac.getBean("msg", MessageBean.class);
		msg.show();
	}
}

第六,傳遞bean對象

<util:list id="fds">
	<value>朋友3</value>
	<value>朋友4</value>
</util:list>

<util:set id="cts">
	<value>城市3</value>
	<value>城市4</value>
</util:set>

<util:map id="boks">
	<entry key="003" value="書3"></entry>
	<entry key="004" value="書4"></entry>
</util:map>

<util:properties id="dbs">
	<prop key="user">root</prop>
	<prop key="password">123456</prop>
</util:properties>

<bean id="msg1" class="org.springioc.bean.MessageBean">
	<property name="friends" ref="fds"></property>
	<property name="cities" ref="cts"></property>
	<property name="books" ref="boks"></property>
	<property name="db" ref="dbs"></property>
</bean>

第七,Spring表達式注入

<bean id="msg1" class="org.springioc.bean.MessageBean">
	<property name="friends" ref="fds"></property>
	<property name="cities" ref="cts"></property>
	<property name="books" ref="boks"></property>
	<property name="db" ref="dbs"></property>
	<!-- 表達式注入 -->
	<property name="name" value="#{fds[0]}"></property>
	<property name="age" value="#{dbs.password}"></property>
</bean>

第八,讀取properties文件
在src目錄下創建db.properties文件,文件內容格式爲key=value:

user=xiaohong
password=321123

配置applicationContext.xml文件,classpath代表src目錄下

<util:properties id="dbParams" location="classpath:db.properties"/>
  1. 組件自動掃描
    組件自動掃描,可以按指定的包路徑,將包下所有組件掃描,如果發現類定義前有以下標記,會將組件掃描到Sping容器
    @Component//其他組件
    @Controller//控制層組件
    @Service//業務層組件 xxxService
    @Repository//數據訪問層組件 xxxDao
    @Named(需要引入第三方jar包,一般用不到!)

@Scope控制對象是否單例,默認單例
@PostConstruct指定init-method
@PreDestroy指定destroy-method

首先配置applicationContext.xml文件

<!-- 開啓組件掃描 -->
<context:component-scan base-package="org.springioc.bean"/>

編寫beanBook.java

package org.springioc.bean;

import org.springframework.stereotype.Component;

@Component//默認id爲類名首字母小寫;也可以設置固定的id,@Component("id")
public class Book {
	private String name;
	private int	num;
	
	public void execute() {
		System.out.println("book的execute方法!");
	}
	public void show() {
		System.out.println("name:"+name+", num:"+num);
	}
}

編寫測試類,BookTest.java

package org.springioc.bean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component//默認id爲類名首字母小寫;也可以設置固定的id,@Component("id")
@Scope("prototype")//設置單例或非單例,不設置默認爲singleton
public class Book {
	private String name;
	private int	num;
	
	@PostConstruct//設置初始化方法
	public void init() {
		System.out.println("初始化方法!");
	}
	
	@PreDestroy//設置方法銷戶方法
	public void destroy() {
		System.out.println("銷燬方法!");
	}
	
	public void execute() {
		System.out.println("book的execute方法!");
	}
}

  1. 注入註解
    @Resource:可以在變量定義前
    setXX方法前應用
    @Autowired:可以在變量定義前
    setXX方法前應用

一般使用時,功能等價,都可以實現注入。
如果不存在多個匹配類型,使用@Resource
或@Autowired都可以。
如果存在多個匹配類型,建議按名稱注入
@Resource(name=“指定名稱”)或
@Autowired
@Qualifier(“p”)

如果指定名稱注入,不會再按類型匹配注入。

新建一個web工程
配置applicationContext.xml

<!-- 開啓組件掃描 -->
<context:component-scan base-package="cn.springioc"/>

編寫Phone.java,Computer.java,Student.java

package cn.springioc.bean;

import org.springframework.stereotype.Component;

@Component
public class Phone {
	public void show(){
		System.out.println("顯示手機配置信息");
	}
}

package cn.springioc.bean;

import org.springframework.stereotype.Component;

@Component
public class Computer {
	
	public void show(){
		System.out.println("顯示計算機配置信息");
	}
}

package cn.springioc.bean;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("st")
public class Student {
	
	@Resource//首先根據名字phone去匹配,如果匹配不到就按照類型去匹配。這裏根據phone匹配能夠找到
	private Phone phone;
	
	public void setPhone(Phone phone) {
		this.phone = phone;
	}
	
	@Autowired//首先根據名字pc去匹配,如果匹配不到就按照類型去匹配。這裏根據pc匹配找不到,就根據類型去匹配
	private Computer pc;
	
	public void setPc(Computer pc) {
		this.pc = pc;
	}
	
	public void show() {
		phone.show();
		pc.show();
	}

}

編寫測試類StudentTest.java

package cn.springioc.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.springioc.bean.Student;

public class StudentTest {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Student st = ac.getBean("st", Student.class);
		st.show();
	}

}

@Resouce(name=“id”),按照名字id去匹配,如果匹配不到不會按照類型去匹配,匹配不到就拋錯

@Resource(name="pc1")//按照名字去匹配pc1,如果找不到就報錯
	private Computer pc;
	public void setPc(Computer pc) {
		this.pc = pc;
	}

將Computer.java,的bean的id改爲pc1,否則會拋錯

@Component("pc1")
public class Computer {
	
	public void show(){
		System.out.println("顯示計算機配置信息");
	}
}

@Autowired 和 @Qualifier(“id”)按照指定的id名字匹配

	@Autowired
	@Qualifier("pc1")
	private Computer pc;
	public void setPc(Computer pc) {
		this.pc = pc;
	}

或則

private Computer pc;
	@Autowired
	public void setPc(@Qualifier("pc1") Computer pc) {
		this.pc = pc;
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章