Java Spring IoC
1. spring概述
1.1 Spring是什麼(理解)
Spring是分層的 Java SE/EE應用 full-stack 輕量級開源框架,以 IoC(Inverse Of Control:反轉控制)和 AOP(Aspect Oriented Programming:面向切面程式設計)為核心。
提供了展現層 SpringMVC和持久層 Spring JDBCTemplate以及業務層事務管理等眾多的企業級應用技術,還能整合開源世界眾多著名的第三方框架和類庫,逐漸成為使用最多的Java EE 企業應用開源框架
1.2 Spring發展歷程 (瞭解)
Rod Johnson ( Spring 之父)
2017 年
9 月份釋出了 Spring 的最新版本 Spring5.0
通用版(GA)
1.3 Spring的優勢(理解)
方便解耦,簡化開發
AOP 程式設計的支援
宣告式事務的支援
方便程式的測試
1.4 Spring的體系結構(瞭解)
2. spring快速入門
2.1 Spring程式開發步驟
①匯入 Spring 開發的基本包座標
②編寫 Dao 介面和實現類
③建立 Spring 核心配置檔案
④在 Spring 配置檔案中配置 UserDaoImpl
⑤使用 Spring 的 API 獲得 Bean 例項
2.2 匯入Spring開發的基本包座標
<properties> <spring.version>5.0.5.RELEASE</spring.version> </properties> <!--匯入spring的context座標,context依賴core、beans、expression--> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
2.3 編寫Dao介面和實現類
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao save method running....");
}
}
2.4 建立Spring核心配置檔案
在類路徑下(resources)建立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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
2.5 在Spring配置檔案中配置UserDaoImpl
<?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="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
</beans>
2.6 使用Spring的API獲得Bean例項
@Test
public void test1(){
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save();
}
3. Spring配置檔案
3.1 Bean標籤基本配置
用於配置物件交由Spring 來建立。
預設情況下它呼叫的是類中的無參建構函式,如果沒有無參建構函式則不能建立成功。
基本屬性:
id:Bean例項在Spring容器中的唯一標識
class:Bean的全限定名稱
3.2 Bean標籤範圍配置
scope:指物件的作用範圍,取值如下:
取值範圍 | 說明 |
---|---|
singleton | 預設值,單例的 |
prototype | 多例的 |
request | WEB 專案中,Spring 建立一個 Bean 的物件,將物件存入到 request 域中 |
session | WEB 專案中,Spring 建立一個 Bean 的物件,將物件存入到 session 域中 |
global session | WEB 專案中,應用在 Portlet 環境,如果沒有 Portlet 環境那麼globalSession 相當於 session |
1)當scope的取值為singleton時
Bean的例項化個數:1個
Bean的例項化時機:當Spring核心檔案被載入時,例項化配置的Bean例項
Bean的生命週期:
物件建立:當應用載入,建立容器時,物件就被建立了
物件執行:只要容器在,物件一直活著
物件銷燬:當應用解除安裝,銷燬容器時,物件就被銷燬了
2)當scope的取值為prototype時
Bean的例項化個數:多個
Bean的例項化時機:當呼叫getBean()方法時例項化Bean
物件建立:當使用物件時,建立新的物件例項
物件執行:只要物件在使用中,就一直活著
物件銷燬:當物件長時間不用時,被 Java 的垃圾回收器回收了
3.3 Bean生命週期配置
init-method:指定類中的初始化方法名稱
destroy-method:指定類中銷燬方法名稱
3.4 Bean例項化三種方式
1) 使用無參構造方法例項化
它會根據預設無參構造方法來建立類物件,如果bean中沒有預設無參建構函式,將會建立失敗
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
2) 工廠靜態方法例項化
工廠的靜態方法返回Bean例項
public class StaticFactoryBean {
public static UserDao createUserDao(){
return new UserDaoImpl();
}
}
<bean id="userDao" class="com.itheima.factory.StaticFactoryBean"
factory-method="createUserDao" />
3) 工廠例項方法例項化
工廠的非靜態方法返回Bean例項
public class DynamicFactoryBean {
public UserDao createUserDao(){
return new UserDaoImpl();
}
}
<bean id="factoryBean" class="com.itheima.factory.DynamicFactoryBean"/>
<bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>
3.5 Bean的依賴注入入門
①建立 UserService,UserService 內部在呼叫 UserDao的save() 方法
public class UserServiceImpl implements UserService {
@Override
public void save() {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.save();
}
}
②將 UserServiceImpl 的建立權交給 Spring
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"/>
③從 Spring 容器中獲得 UserService 進行操作
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.save();
3.6 Bean的依賴注入概念
依賴注入(Dependency Injection):它是 Spring 框架核心 IOC 的具體實現。
在編寫程式時,通過控制反轉,把物件的建立交給了 Spring,但是程式碼中不可能出現沒有依賴的情況。
IOC 解耦只是降低他們的依賴關係,但不會消除。例如:業務層仍會呼叫持久層的方法。
那這種業務層和持久層的依賴關係,在使用 Spring 之後,就讓 Spring 來維護了。
簡單的說,就是坐等框架把持久層物件傳入業務層,而不用我們自己去獲取
3.7 Bean的依賴注入方式
①構造方法
建立有參構造
public class UserServiceImpl implements UserService {
@Override
public void save() {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.save();
}
}
配置Spring容器呼叫有參構造時進行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
②set方法
在UserServiceImpl中新增setUserDao方法
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
配置Spring容器呼叫set方法進行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
set方法:P名稱空間注入
P名稱空間注入本質也是set方法注入,但比起上述的set方法注入更加方便,主要體現在配置檔案中,如下:
首先,需要引入P名稱空間:
xmlns:p="http://www.springframework.org/schema/p"
其次,需要修改注入方式
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl" p:userDao-
ref="userDao"/>
3.8 Bean的依賴注入的資料型別
上面的操作,都是注入的引用Bean,處了物件的引用可以注入,普通資料型別,集合等都可以在容器中進行注入。
注入資料的三種資料型別
普通資料型別
引用資料型別
集合資料型別
其中引用資料型別,此處就不再贅述了,之前的操作都是對UserDao物件的引用進行注入的,下面將以set方法注入為例,演示普通資料型別和集合資料型別的注入。
Bean的依賴注入的資料型別
(1)普通資料型別的注入
public class UserDaoImpl implements UserDao {
private String company;
private int age;
public void setCompany(String company) {
this.company = company;
}
public void setAge(int age) {
this.age = age;
}
public void save() {
System.out.println(company+"==="+age);
System.out.println("UserDao save method running....");
}
}
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="company" value="傳智播客"></property>
<property name="age" value="15"></property>
</bean>
(2)集合資料型別(List
public class UserDaoImpl implements UserDao {
private List<String> strList;
public void setStrList(List<String> strList) {
this.strList = strList;
}
public void save() {
System.out.println(strList);
System.out.println("UserDao save method running....");
}
}
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="strList">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
</bean>
(3)集合資料型別(List
public class UserDaoImpl implements UserDao {
private List<User> userList;
public void setUserList(List<User> userList) {
this.userList = userList;
}
public void save() {
System.out.println(userList);
System.out.println("UserDao save method running....");
}
}
<bean id="u1" class="com.itheima.domain.User"/>
<bean id="u2" class="com.itheima.domain.User"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="userList">
<list>
<bean class="com.itheima.domain.User"/>
<bean class="com.itheima.domain.User"/>
<ref bean="u1"/>
<ref bean="u2"/>
</list>
</property>
</bean>
(4)集合資料型別( Map<String,User> )的注入
public class UserDaoImpl implements UserDao {
private Map<String,User> userMap;
public void setUserMap(Map<String, User> userMap) {
this.userMap = userMap;
}
public void save() {
System.out.println(userMap);
System.out.println("UserDao save method running....");
}
}
<bean id="u1" class="com.itheima.domain.User"/>
<bean id="u2" class="com.itheima.domain.User"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="userMap">
<map>
<entry key="user1" value-ref="u1"/>
<entry key="user2" value-ref="u2"/>
</map>
</property>
</bean>
(5)集合資料型別(Properties)的注入
public class UserDaoImpl implements UserDao {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
public void save() {
System.out.println(properties);
System.out.println("UserDao save method running....");
}
}
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
<property name="properties">
<props>
<prop key="p1">aaa</prop>
<prop key="p2">bbb</prop>
<prop key="p3">ccc</prop>
</props>
</property>
</bean>
3.9 引入其他配置檔案(分模組開發)
實際開發中,Spring的配置內容非常多,這就導致Spring配置很繁雜且體積很大,所以,可以將部分配置拆解到其他配置檔案中,而在Spring主配置檔案通過import標籤進行載入
<import resource="applicationContext-xxx.xml"/>
4. spring相關API
4.1 ApplicationContext的繼承體系
applicationContext:介面型別,代表應用上下文,可以通過其例項獲得 Spring 容器中的 Bean 物件
4.2 ApplicationContext的實現類
1)ClassPathXmlApplicationContext
它是從類的根路徑下載入配置檔案 推薦使用這種
2)FileSystemXmlApplicationContext
它是從磁碟路徑上載入配置檔案,配置檔案可以在磁碟的任意位置。
3)AnnotationConfigApplicationContext
當使用註解配置容器物件時,需要使用此類來建立 spring 容器。它用來讀取註解。
4.3 getBean()方法使用
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
public <T> T getBean(Class<T> requiredType) throws BeansException { assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
其中,當引數的資料型別是字串時,表示根據Bean的id從容器中獲得Bean例項,返回是Object,需要強轉。
當引數的資料型別是Class型別時,表示根據型別從容器中匹配Bean例項,當容器中相同型別的Bean有多個時,則此方法會報錯
getBean()方法使用
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService1 = (UserService) applicationContext.getBean("userService");
UserService userService2 = applicationContext.getBean(UserService.class);