@
人生的態度是:抱有最大的希望。
盡最大的努力,做最壞的打算。
—————— 柏拉圖《理想國》
閱讀以下程式碼:
package com.powernode.oa.controller;
import com.powernode.oa.service.UserService;
import com.powernode.oa.service.impl.UserServiceImpl;
public class UserController {
private UserService userService = new UserServiceImpl();
public void login(){
String username = "admin";
String password = "123456";
boolean success = userService.login(username, password);
if (success) {
// 登入成功
} else {
// 登入失敗
}
}
}
package com.powernode.oa.service.impl;
import com.powernode.oa.bean.User;
import com.powernode.oa.dao.UserDao;
import com.powernode.oa.dao.impl.UserDaoImplForMySQL;
import com.powernode.oa.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImplForMySQL();
public boolean login(String username, String password) {
User user = userDao.selectByUsernameAndPassword(username, password);
if (user != null) {
return true;
}
return false;
}
}
package com.powernode.oa.dao.impl;
import com.powernode.oa.bean.User;
import com.powernode.oa.dao.UserDao;
public class UserDaoImplForMySQL implements UserDao {
public User selectByUsernameAndPassword(String username, String password) {
// 連線MySQL資料庫,根據使用者名稱和密碼查詢使用者資訊
return null;
}
}
可以看出,UserDaoImplForMySQL中主要是連線MySQL資料庫進行操作。如果更換到Oracle資料庫上,則需要再提供一個UserDaoImplForOracle,如下:
package com.powernode.oa.dao.impl;
import com.powernode.oa.bean.User;
import com.powernode.oa.dao.UserDao;
public class UserDaoImplForOracle implements UserDao {
public User selectByUsernameAndPassword(String username, String password) {
// 連線Oracle資料庫,根據使用者名稱和密碼查詢使用者資訊
return null;
}
}
很明顯,以上的操作正在進行功能的擴充套件,新增了一個新的類UserDaoImplForOracle來應付資料庫的變化,這裡的變化會引起連鎖反應嗎?當然會,如果想要切換到Oracle資料庫上,UserServiceImpl類程式碼就需要修改,如下:
package com.powernode.oa.service.impl;
import com.powernode.oa.bean.User;
import com.powernode.oa.dao.UserDao;
import com.powernode.oa.dao.impl.UserDaoImplForOracle;
import com.powernode.oa.service.UserService;
public class UserServiceImpl implements UserService {
//private UserDao userDao = new UserDaoImplForMySQL();
private UserDao userDao = new UserDaoImplForOracle();
public boolean login(String username, String password) {
User user = userDao.selectByUsernameAndPassword(username, password);
if (user != null) {
return true;
}
return false;
}
}
這樣一來就違背了開閉原則OCP。開閉原則是這樣說的:在軟體開發過程中應當對擴充套件開放,對修改關閉。
也就是說,如果在進行功能擴充套件的時候,新增額外的類是沒問題的,但因為功能擴充套件而修改之前執行正常的程式(程式碼),這是忌諱的,不被允許的。因為一旦修改之前執行正常的程式,就會導致專案整體要進行全方位的重新測試。這是相當麻煩的過程。導致以上問題的主要原因是:程式碼和程式碼之間的耦合度太高。如下圖所示:
可以很明顯的看出,上層是依賴下層的。UserController依賴UserServiceImpl,而UserServiceImpl依賴UserDaoImplForMySQL,這樣就會導致下面只要改動,上面必然會受牽連(跟著也會改),所謂牽一髮而動全身。這樣也就同時違背了另一個開發原則:依賴倒置原則。
依賴倒置原則(Dependence Inversion Principle),簡稱DIP,主要倡導面向抽象程式設計,面向介面程式設計,不要面向具體程式設計,讓上層不再依賴下層,下面改動了,上面的程式碼不會受到牽連。這樣可以大大降低程式的耦合度,耦合度低了,擴充套件力就強了,同時程式碼複用性也會增強。(軟體七大開發原則都是在為解耦合服務)
你可能會說,上面的程式碼已經面向介面程式設計了呀:
確實已經面向介面程式設計了,但物件的建立是:new UserDaoImplForOracle()顯然並沒有完全面向介面程式設計,還是使用到了具體的介面實現類。什麼叫做完全面向介面程式設計?什麼叫做完全符合依賴倒置原則呢?請看以下程式碼:
如果程式碼是這樣編寫的,才算是完全面向介面程式設計,才符合依賴倒置原則。那你可能會問,這樣userDao是null,在執行的時候就會出現空指標異常呀。你說的有道理,確實是這樣的,所以我們要解決這個問題。解決空指標異常的問題,其實就是解決兩個核心的問題:
如果我們把以上兩個核心問題解決了,就可以做到既符合OCP開閉原則,又符合依賴倒置原則。
很榮幸的通知你:Spring框架可以做到。
在Spring框架中,它可以幫助我們new物件,並且它還可以將new出來的物件賦到屬性上。換句話說,Spring框架可以幫助我們建立物件,並且可以幫助我們維護物件和物件之間的關係。比如:
Spring可以new出來UserDaoImplForMySQL物件,也可以new出來UserDaoImplForOracle物件,並且還可以讓new出來的dao物件和service物件產生關係(產生關係其實本質上就是給屬性賦值)。
很顯然,這種方式是將物件的建立權/管理權交出去了,不再使用寫死的方式了。同時也把物件關係的管理權交出去了,也不再使用寫死的方式了。像這種把物件的建立權交出去,把物件關係的管理權交出去,被稱為控制反轉。
控制反轉(Inversion of Control,縮寫為IoC),是物件導向程式設計中的一種設計思想,可以用來降低程式碼之間的耦合度,符合依賴倒置原則。
控制反轉的核心是:將物件的建立權交出去,將物件和物件之間關係的管理權交出去,由第三方容器來負責建立與維護。簡單的說:就是可以幫你建立物件(new 物件)這個步驟:不需要你手動的 new 物件了。
控制反轉常見的實現方式:依賴注入(Dependency Injection,簡稱DI)
通常,依賴注入的實現由包括兩種方式:
而Spring框架就是一個實現了IoC思想的框架。
IoC可以認為是一種全新的設計模式,但是理論和時間成熟相對較晚,並沒有包含在GoF中。(GoF指的是23種設計模式)
Spring 是一個開源框架,它由Rod Johnson 建立。它是為了解決企業應用開發的複雜性而建立的
從簡單性,可測試性和鬆耦合的角度而言,任何Java應用都可以從 Spring 中收益。
Spring 是一種輕量級的控制反轉(IOC) 和麵向切面(ADP) 的容器框架。
Spring 最初的出現是為了解決EJB隆腫的設計,以及難以測試等問題。
Spring 為此簡化開發而生,讓程式設計師只需關注核心業務的實現,儘可能的不再關注非業務邏輯程式碼(事務控制,安全紀錄檔等)
注意:Spring5版本之後是8個模組。在Spring5中新增了WebFlux模組。
這是Spring框架最基礎的部分,它提供了依賴注入(DependencyInjection)特徵來實現容器對Bean的管理。核心容器的主要元件是 BeanFactory,BeanFactory是工廠模式的一個實現,是任何Spring應用的核心。它使用IoC將應用設定和依賴從實際的應用程式碼中分離出來。
如果說核心模組中的BeanFactory使Spring成為容器的話,那麼上下文模組就是Spring成為框架的原因。
這個模組擴充套件了BeanFactory,增加了對國際化(I18N)訊息、事件傳播、驗證的支援。另外提供了許多企業服務,例如電子郵件、JNDI存取、EJB整合、遠端以及時序排程(scheduling)服務。也包括了對模版框架例如Velocity和FreeMarker整合的支援
Spring在它的AOP模組中提供了對面向切面程式設計的豐富支援,Spring AOP 模組為基於 Spring 的應用程式中的物件提供了事務管理服務。通過使用 Spring AOP,不用依賴元件,就可以將宣告性事務管理整合到應用程式中,可以自定義攔截器、切點、紀錄檔等操作。
提供了一個JDBC的抽象層和異常層次結構,消除了煩瑣的JDBC編碼和資料庫廠商特有的錯誤程式碼解析,用於簡化JDBC。
Spring提供了ORM模組。Spring並不試圖實現它自己的ORM解決方案,而是為幾種流行的ORM框架提供了整合方案,包括Hibernate、JDO和iBATIS SQL對映,這些都遵從 Spring 的通用事務和 DAO 異常層次結構。
Spring為構建Web應用提供了一個功能全面的MVC框架。雖然Spring可以很容易地與其它MVC框架整合,例如Struts,但Spring的MVC框架使用IoC對控制邏輯和業務物件提供了完全的分離。
Spring Framework 中包含的原始 Web 框架 Spring Web MVC 是專門為 Servlet API 和 Servlet 容器構建的。反應式堆疊 Web 框架 Spring WebFlux 是在 5.0 版的後期新增的。它是完全非阻塞的,支援反應式流(Reactive Stream)背壓,並在Netty,Undertow和Servlet 3.1+容器等伺服器上執行。
Web 上下文模組建立在應用程式上下文模組之上,為基於 Web 的應用程式提供了上下文,提供了Spring和其它Web框架的整合,比如Struts、WebWork。還提供了一些面向服務支援,例如:實現檔案上傳的multipart請求。
輕量
控制反轉
面向切面
容器
框架
所有Spring的這些特徵使你能夠編寫更乾淨、更可管理、並且更易於測試的程式碼。它們也為Spring中的各種模組提供了基礎支援。
官網地址:https://spring.io/
官網地址(中文):http://spring.p2hp.com/
開啟Spring官網後,可以看到Spring Framework,以及通過Spring Framework衍生的其它框架:
我們即將要學習的就是Spring Framework。
怎麼下載呢?
點選spring-5.3.9-dist.zip下載spring框架。
將下載的zip包解壓:
docs:spring框架的API幫助檔案
libs:spring框架的jar檔案(用spring框架就是用這些jar包)
schema:spring框架的XML組態檔相關的約束檔案
開啟libs目錄,會看到很多jar包:
spring-core-5.3.9.jar:位元組碼(這個是支撐程式執行的jar包)
spring-core-5.3.9-javadoc.jar:程式碼中的註釋
spring-core-5.3.9-sources.jar:原始碼
我們來看一下spring框架都有哪些jar包:
JAR檔案 | 描述 |
---|---|
spring-aop-5.3.9.jar | 這個jar 檔案包含在應用中使用Spring 的AOP 特性時所需的類 |
spring-aspects-5.3.9.jar | 提供對AspectJ的支援,以便可以方便的將面向切面的功能整合進IDE中 |
spring-beans-5.3.9.jar | 這個jar 檔案是所有應用都要用到的,它包含存取組態檔、建立和管理bean 以及進行Inversion ofControl / Dependency Injection(IoC/DI)操作相關的所有類。如果應用只需基本的IoC/DI 支援,引入spring-core.jar 及spring-beans.jar 檔案就可以了。 |
spring-context-5.3.9.jar | 這個jar 檔案為Spring 核心提供了大量擴充套件。可以找到使用Spring ApplicationContext特性時所需的全部類,JDNI 所需的全部類,instrumentation元件以及校驗Validation 方面的相關類。 |
spring-context-indexer-5.3.9.jar | 雖然類路徑掃描非常快,但是Spring內部存在大量的類,新增此依賴,可以通過在編譯時建立候選物件的靜態列表來提高大型應用程式的啟動效能。 |
spring-context-support-5.3.9.jar | 用來提供Spring上下文的一些擴充套件模組,例如實現郵件服務、檢視解析、快取、定時任務排程等 |
spring-core-5.3.9.jar | Spring 框架基本的核心工具類。Spring 其它元件要都要使用到這個包裡的類,是其它元件的基本核心,當然你也可以在自己的應用系統中使用這些工具類。 |
spring-expression-5.3.9.jar | Spring表示式語言。 |
spring-instrument-5.3.9.jar | Spring3.0對伺服器的代理介面。 |
spring-jcl-5.3.9.jar | Spring的紀錄檔模組。JCL,全稱為"Jakarta Commons Logging",也可稱為"Apache Commons Logging"。 |
spring-jdbc-5.3.9.jar | Spring對JDBC的支援。 |
spring-jms-5.3.9.jar | 這個jar包提供了對JMS 1.0.2/1.1的支援類。JMS是Java訊息服務。屬於JavaEE規範之一。 |
spring-messaging-5.3.9.jar | 為整合messaging api和訊息協定提供支援 |
spring-orm-5.3.9.jar | Spring整合ORM框架的支援,比如整合hibernate,mybatis等。 |
spring-oxm-5.3.9.jar | 為主流O/X Mapping元件提供了統一層抽象和封裝,OXM是Object Xml Mapping。物件和XML之間的相互轉換。 |
spring-r2dbc-5.3.9.jar | Reactive Relational Database Connectivity (關係型資料庫的響應式連線) 的縮寫。這個jar檔案是Spring對r2dbc的支援。 |
spring-test-5.3.9.jar | 對Junit等測試框架的簡單封裝。 |
spring-tx-5.3.9.jar | 為JDBC、Hibernate、JDO、JPA、Beans等提供的一致的宣告式和程式設計式事務管理支援。 |
spring-web-5.3.9.jar | Spring整合MVC框架的支援,比如整合Struts等。 |
spring-webflux-5.3.9.jar | WebFlux是 Spring5 新增的新模組,用於 web 的開發,功能和 SpringMVC 類似的,Webflux 使用當前一種比較流程響應式程式設計出現的框架。 |
spring-webmvc-5.3.9.jar | SpringMVC框架的類庫 |
spring-websocket-5.3.9.jar | Spring整合WebSocket框架時使用 |
這裡我們不是使用上面的方式下載的: 而是通過:Maven 自動化管理工具:
<!-- spring6 框架-->
<!--spring contest 倉庫-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
注意:如果你只是想用Spring的IoC功能,僅需要引入:spring-context即可。將這個jar包新增到classpath當中。
如果採用maven只需要引入context的依賴即可。
<!--Spring6的正式版釋出之前,這個倉庫地址是需要的-->
<repositories>
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<dependencies>
<!-- spring6 框架-->
<!--spring contest 倉庫-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
</dependencies>
設定該專案的 JDK為 17
注意的是: 對應 Spring6 來說:最低支援的是 JDK17 ,低於 17 的版本是不行的,所以如果你要想使用 Spring6 框架的話,必須安裝 JDK > = 17 的版本才行。
第一步:設定好該專案中的Maven本地路徑資訊:
第二步:新增spring context的依賴,pom.xml設定如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.raibowsea</groupId>
<artifactId>spring6-003-dependency-injection</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 將專案的打包方式為 jar Java專案的方式-->
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<!-- 匯入相關的依賴倉庫-->
<dependencies>
<!-- spring6 框架-->
<!--spring contest 倉庫-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
<!-- junit4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.19.0</version>
</dependency>
</dependencies>
</project>
注意:打包方式jar。
當加入spring context的依賴之後,會關聯引入其他依賴:
spring aop:面向切面程式設計
spring beans:IoC核心
spring core:spring的核心工具包
spring jcl:spring的紀錄檔包
spring expression:spring表示式
第三步: bean : User
在:Spring 框架中,每一個管理的類,都是 bean ,在 xml 中基本上面向 bean 編寫的。
package com.rainbowsea.spring6.bean;
/**
* 這是一個bean ,封裝了使用者的資訊,Spring 可以幫助我們建立User物件嗎?
*
*/
public class User {
// Spring 是怎麼範例化物件的?
// 預設情況下Spring 是通過反射機制,呼叫類的無引數構造方法來範例化物件的
// 所以,對於反射來說,我們來要有,一定要有私有的構造器
// Class<?> clazz = Class.forName("com.rainbowsea.spring6.bean.User");
// Object o = clazz.newInstance();
public User () {
System.out.println("User 的無引數構造器構造方法的執行");
}
}
第四步:編寫spring的組態檔:beans.xml。該檔案放在類的根路徑下。
上圖是使用IDEA工具自帶的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">
</beans>
對 Spring 組態檔中進行 bean 的設定:
**注意: **
<?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="userBean2" class="com.rainbowsea.spring6.bean.User"></bean>
<!-- id 屬性: 代表物件的唯一標識,可以看做一個人的身份證號:-->
<!-- class 屬性: 用來指定要建立的 java 物件的類名,這個類名必須是全限定類名(帶包名)-->
</beans>
第五步:編寫測試程式
這裡我們使用: JUit4 的測試:
package com.rainbowsea.spring6;
import com.rainbowsea.spring6.bean.User;
import com.rainbowsea.spring6.bean.UserDao;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FirstSpringTest {
@Test
public void testFirstSpringCode() {
// 第一步:獲取到Spring 容器物件
// ApplicationContext 翻譯為: 應用上下文,其實就是
// ApplicationContext 是一個介面:
// ApplicationContest 介面下有很多實現類,其中有一個實現類叫做:ClassPathXmlApplicationContext
// ClassPathXmlApplicationContext 專門從類路徑當中載入Spring 組態檔的一個類
// 下面這行程式碼只要執行,就相當與啟動了/Spring 容器,解析Spring.xml 檔案.
// 面向介面程式設計,左邊的是介面,右邊的類
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
/**
* 原始碼分析:
* public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
* this(configLocations, true, (ApplicationContext)null);
* }
* 可變引數,說明可以傳入多個引數西資訊;
*
*/
// 第二步: 根據bean 的id從Spring 的容器中獲取到這個物件
// 注意:這個name ,儘量使用 copy 的方式,防止發生錯誤
Object userBean = applicationContext.getBean("userBean");
System.out.println(userBean);
}
}
<bean id="userBean" class="com.powernode.spring6.bean.User"/>
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object userBean = applicationContext.getBean("userBean");
注意: 在 Spring 當中的 xml
中對應設定的 bean 中的 id屬性的值是不可以重複的,它就像人的身份證號一樣的,不可重複。
package com.powernode.spring6.bean;
public class Vip {
}
<?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="userBean" class="com.powernode.spring6.bean.User"/>
<bean id="userBean" class="com.powernode.spring6.bean.Vip"/>
<--這裡我們的 id 重複了,測試-->
</beans>
執行測試程式:
通過測試得出:在spring的組態檔中id是不能重名。
package com.powernode.spring6.bean;
public class User {
public User() {
System.out.println("User的無引數構造方法執行");
}
}
在User類中新增無引數構造方法,如上。
執行測試程式:
通過測試得知:建立物件時確實呼叫了無引數構造方法。
如果提供一個有引數構造方法,不提供無引數構造方法會怎樣呢?
package com.powernode.spring6.bean;
public class User {
/*public User() {
System.out.println("User的無引數構造方法執行");
}*/
public User(String name){
System.out.println("User的有引數構造方法執行");
}
}
執行測試程式:
通過測試得知:spring是通過呼叫類的無引數構造方法來建立物件的,所以要想讓spring給你建立物件,必須保證無引數構造方法是存在的。
Spring是如何建立物件的呢?原理是什麼?
// dom4j解析beans.xml檔案,從中獲取class的全限定類名
// 通過反射機制呼叫無引數構造方法建立物件
Class clazz = Class.forName("com.powernode.spring6.bean.User");
Object obj = clazz.newInstance();
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
通過以上的java程式碼可以看出,這個spring組態檔名字是我們負責提供的,顯然spring組態檔的名字是隨意的。
再建立一個spring組態檔,起名:spring.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="vipBean" class="com.powernode.spring6.bean.Vip"/>
</beans>
package com.powernode.spring6.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Spring6Test {
@Test
public void testFirst(){
// 初始化Spring容器上下文(解析beans.xml檔案,建立所有的bean物件)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml","spring.xml");
// 根據id獲取bean物件
Object userBean = applicationContext.getBean("userBean");
Object vipBean = applicationContext.getBean("vipBean");
System.out.println(userBean);
System.out.println(vipBean);
}
}
執行測試程式:
通過測試得知,spring的組態檔可以有多個,在ClassPathXmlApplicationContext構造方法的引數上傳遞檔案路徑即可。這是為什麼呢?通過原始碼可以看到:
<?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="userBean" class="com.powernode.spring6.bean.User"/>
<!--<bean id="userBean" class="com.powernode.spring6.bean.Vip"/>-->
<bean id="dateBean" class="java.util.Date"/>
</beans>
package com.powernode.spring6.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Spring6Test {
@Test
public void testFirst(){
// 初始化Spring容器上下文(解析beans.xml檔案,建立所有的bean物件)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml","spring.xml");
// 根據id獲取bean物件
Object userBean = applicationContext.getBean("userBean");
Object vipBean = applicationContext.getBean("vipBean");
Object dateBean = applicationContext.getBean("dateBean");
System.out.println(userBean);
System.out.println(vipBean);
System.out.println(dateBean);
}
}
執行測試程式:
通過測試得知,在spring組態檔中設定的bean可以任意類,只要這個類不是抽象的,並且提供了無引數構造方法。
執行測試程式:
通過測試得知,當id不存在的時候,會出現異常。
User user = applicationContext.getBean("userBean", User.class);
<?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="vipBean2" class="com.powernode.spring6.bean.Vip"/>
</beans>
ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("d:/spring6.xml");
Vip vip = applicationContext2.getBean("vipBean2", Vip.class);
System.out.println(vip);
沒有在類路徑中的話,需要使用FileSystemXmlApplicationContext類進行載入組態檔。注意: 如果在類的路徑當中,讀取到的是類路徑下的子目錄下的 xml 檔案資訊,需要指明對應的 類路徑下的子目錄,不然無法讀取到其中的 xml 檔案資訊的。
這種方式較少用。一般都是將組態檔放到類路徑當中,這樣可移植性更強。
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
Object vipBean = beanFactory.getBean("vipBean");
System.out.println(vipBean);
BeanFactory是Spring容器的超級介面。ApplicationContext是BeanFactory的子介面。
第一步:引入Log4j2的依賴
<!--log4j2的依賴-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.19.0</version>
</dependency>
第二步:在類的根路徑下提供log4j2.xml組態檔(檔名固定為:log4j2.xml,檔案必須放到類根路徑下。)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<loggers>
<!--
level指定紀錄檔級別,從低到高的優先順序:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
-->
<root level="DEBUG">
<appender-ref ref="spring6log"/>
</root>
</loggers>
<appenders>
<!--輸出紀錄檔資訊到控制檯-->
<console name="spring6log" target="SYSTEM_OUT">
<!--控制紀錄檔輸出的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
</console>
</appenders>
</configuration>
第三步:使用紀錄檔框架
Logger logger = LoggerFactory.getLogger(FirstSpringTest.class);
logger.info("我是一條紀錄檔訊息");
<!-- spring6 框架-->
<!--spring contest 倉庫-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.3</version>
</dependency>
ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("d:/spring6.xml");
Vip vip = applicationContext2.getBean("vipBean2", Vip.class);
System.out.println(vip);
「在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。」