文章目錄
Spring
Spring介紹
-
Spring框架是由於軟件開發的複雜性而創建的。Spring使用的是基本的JavaBean來完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限於服務器端的開發。從簡單性、可測試性和鬆耦合性角度而言,絕大部分Java應用都可以從Spring中受益。
Spring優點
- DI(Dependency Injection)與IOC(Inverse Of Control)
- AOP(Aspect Oriented Programming)
- 與所有框架完美集成
- 使得JDBC/事務等更加方便
Spring容器和IOC與DI思想
Spring容器爲我們管理對象的創建和銷燬全過程
對於像jdbc或是連接池需要經歷一系列的對象創建、使用和銷燬過程的項目,在需求越來越大,對應的對象越來越多,整個過程如果通過我們自己去處理將會十分複雜.
Spring容器通過依賴注入,和自動裝配(過程)實現控制反轉(結果)
類與類之間的依賴關係若通過new構造方法創建對象的方式解決,耦合性太強.Spring獲得創建對象的控制權,程序需要什麼對象,只要去容器中取
- DI(Dependency Injection)依賴注入就是不通過原始的方法創建對象實例,而是通過自動裝配(底層通過反射實現)依賴容器爲程序注入對象,自動裝配通過配置文件,反射來獲取程序需要的對象類型、實例名
- IOC(Inverse Of Control)控制反轉:將實例化對象的控制權交給Spring容器
Spring配置
IOCjar包介紹
jar包 | 概述 |
---|---|
Spring-core | Spring的核心工具包,spring的其它包都要用到該jar中的包 |
Spring-beans | 包含配置文件,bean的創建等,所有jar包都需要用到 |
Spring-context | 在上面兩個jar完成基礎IOC功能上提供擴展服務,此外還提供許多企業級服務的支持,有郵件服務、任務調度、JNDI定位,EJB集成、遠程訪問、緩存以及多種視圖層框架的支持。 |
Spring-expression | Spring表達式語言,spel表達式,SpEL支持標準數學運算符,關係運算符,邏輯運算符,條件運算符,集合和正則表達式等。 |
Spring-context-support | Spring context的擴展支持,用於MVC方面,比如支持freemarker等模板引擎 |
Maven引入jar包
<properties>
<spring.version>5.1.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source> <!-- 源代碼使用jdk1.8支持的特性 -->
<target>1.8</target> <!-- 使用jvm1.8編譯目標代碼 -->
<compilerArgs> <!-- 傳遞參數 -->
<arg>-parameters</arg>
<arg>-Xlint:unchecked</arg>
<arg>-Xlint:deprecation </arg>
</compilerArgs>
</configuration>
</plugin>
日誌配置
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.26</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
在resources文件夾中加入log4j.properties
log4j.rootCategory=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
IOC配置文件
在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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
Spring案例剖析
配置文件加入
-
創建Maven普通項目,添加jar包以及配置文件.
-
創建StudentService類,在applicationCotext中配置類信息
<bean id="studentService" class="com.edu.bean.StudentService"></bean>
-
創建測試,在鼠標點擊類名按下
Alt
+Enter
選擇Create Test
,最後在測試方法註解中去掉org.junit.
並導入junit包@Test public void show() { //1、加載容器,通過配置文件加載ApplicationContext,beanFactory(原始)(SpringIOC容器) //classpath:會在當前項目resources下面去找(編譯後target下面找) //classpath*:查找除了在本項目包括其他項目的jar包的resources文件夾路徑 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml"); //2、創建對象 StudentService studentService = (StudentService) context.getBean("studentService"); //3、調用對象方法 studentService.show(); //4、銷燬 //classPathXmlApplicationContext.close(); context.registerShutdownHook();//更爲優雅 }
bean標籤屬性詳解
id/name
對象的唯一標識,兩者性質一樣,value
也不能相同
Scope
設置對象的實例類型
值 | 概述 |
---|---|
singleton | SpringIoc容器只會創建該Bean的唯一實例,所有的請求和引用都只使用這個實例 |
prototype | 每次請求都創建一個實例 |
request | 在一次Http請求中,容器會返回該Bean的同一個實例,而對於不同的用戶請求,會返回不同的實例。需要注意的是,該作用域僅在基於Web的Spring ApplicationContex t情形下有效,以下的session和global Session也是如此 |
session | 同上,唯一的區別是請求的作用域變爲了session |
global session | 全局的HttpSession 中 |
autowire:自動裝配
爲依賴的javabean設置自動裝配的方式,在原對象中必須創建getter,setter(javabean規範),框架底層調用實現
值 | 概述 |
---|---|
no | 即不啓用自動裝配。autowire默認的值。 |
byName | 通過屬性的名字的方式查找JavaBean依賴的對象併爲其注入,使用Seter 方法爲其注入。 |
byType | 通過屬性的類型查找JavaBean依賴的對象併爲其注入。使用Seter 方法爲其注入 |
constructor | 通byType 一樣,也是通過類型查找依賴對象。與byType的區別在於它不是使用Seter 方法注入,而是使用構造子注入 |
autodetect | 在byType和constructor之間自動的選擇注入方式 |
default | 由上級標籤的default-autowire屬性確定 |
注意:在配置bean時,標籤中autowire屬性的優先級比其上級標籤高,即是說,如果在上級標籤中定義default-autowire屬性爲byName,而在中定義爲byType時,Spring IoC容器會優先使用標籤的配置。
factory-bean/factory-method 工廠方法注入
<bean factory-bean="" factory-method=""></bean>
lazy-init:延遲加載
值爲true時,在Spring容器初始化時該javabean不加載而是等到程序使用該類時加載
默認值爲false,javabean會隨着Spring容器一同被加載.
注意:
- lazy-init只有在scope爲singleton(單例)時才生效
- 若lazy-init的javabean被不是lazy-init依賴,則前者被後者第一次主動使用,兩者同時加載
init-method/destroy-method
初始化(構造方法先執行)和銷燬前javabean時調用的方法
關於在spring 容器初始化 bean 和銷燬前所做的操作定義方式有三種:
第一種:通過@PostConstruct 和 @PreDestroy 方法 實現初始化和銷燬bean之前進行的操作
第二種是:通過 在xml中定義init-method 和 destory-method方法
第三種是: 通過bean實現InitializingBean和 DisposableBean接口
Spring容器架構
ApplicationContext
類名 | 概述 |
---|---|
AnnotationConfigApplicationContext | 基於註解開發時使用的容器 |
ClassPathXmlApplicationContext | 查找配置文件時默認到classpath路徑下去找,也就是編譯後的classes文件夾 |
FileSystemXmlApplicationContext | 查找配置文件默認到當前項目的文件系統路徑 |
AnnotationConfigApplicationContext案例分析
//@Configuration標記的方法將該類描述爲配置類,就類似一個xml配置文件,其中多個@Bean標記的方法將被AnnotationConfig(Web)ApplicationContext對象掃描,並用於構造javabean,初始化Spring容器
@Configuration
public class MyConfig {
//@Bean註解標記的方法返回的bean將被交與容器管理並在容器中以name的value值作爲標識
@Bean(name = "studentService")
public StudentService getstudentService()
{
return new StudentService();
}
}
public class AnnoConfigTest {
@Test
public void show()
{
//1、通過註解構造的配置類獲取容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
//2、獲取對象實例
StudentService service = context.getBean(StudentService.class);
service.start();
//3、銷燬
context.registerShutdownHook();
}
}
BeanFactory和ApplicationContext的區別
BeanFactory
是Spring裏面最低層的接口,提供了最簡單的容器的功能,只提供了實例化對象和拿對象的功能;
ApplicationContext
應用上下文,繼承BeanFactory接口,它是Spring的一各更高級的容器,提供了更多的有用的功能;
-
國際化(MessageSource)
-
訪問資源,如URL和文件(ResourceLoader)
-
載入多個(有繼承關係)上下文 ,使得每一個上下文都專注於一個特定的層次,比如應用的web層
-
消息發送、響應機制(ApplicationEventPublisher)
-
AOP(攔截器)
兩者裝載bean的區別
BeanFactory
BeanFactory在啓動的時候不會去實例化Bean,中有從容器中拿Bean的時候纔會去實例化;
ApplicationContext
ApplicationContext在啓動的時候就把所有的Bean全部實例化了。它還可以爲Bean配置lazy-init=true來讓Bean延遲實例化;
選擇
延遲實例化的優點:(BeanFactory)
應用啓動的時候佔用資源很少;對資源要求較高的應用,比較有優勢;
不延遲實例化的優點: (ApplicationContext)
- 所有的Bean在啓動的時候都加載,系統運行的速度快;
- 在啓動的時候所有的Bean都加載了,我們就能在系統啓動的時候,儘早的發現系統中的配置問題
- 建議web應用,在啓動的時候就把所有的Bean都加載了。(把費時的操作放到系統啓動中完成)
SpringAPI
spring的getBean方法
依賴注入(兩種)
setter注入
<bean class="com.edu.bean.Student">
<!-- int-->
<property name="age" value="23" ></property>
<!-- String-->
<property name="name" value="DLz"></property>
<!-- Array-->
<property name="friends">
<array>
<value>zyh</value>
<value>rit</value>
<value>laz</value>
</array>
</property>
<!-- List-->
<property name="girlfriends">
<list>
<value>zjey</value>
</list>
</property>
<!-- Set<Object>-->
<property name="courses">
<set>
<bean class="com.edu.bean.Course">
<property name="id" value="1"/>
<property name="name" value="語文"/>
</bean>
<bean class="com.edu.bean.Course">
<property name="id" value="2"/>
<property name="name" value="數學"/>
</bean>
</set>
</property>
<!-- Properties-->
<property name="score">
<props>
<prop key="1">88</prop>
<prop key="2">100</prop>
</props>
</property>
</bean>
構造注入
<bean class="com.edu.bean.Student">
<constructor-arg index="0" value="Dlz"/>
<constructor-arg index="1" value="23"/>
<constructor-arg index="2">
<list>
<value>sjw</value>
<value>jyx</value>
</list>
</constructor-arg>
<constructor-arg index="3">
<list>
<value>zzyy</value>
</list>
</constructor-arg>
<constructor-arg index="4">
<set>
<bean class="com.edu.bean.Course">
<property name="id" value="1"/>
<property name="name" value="語文"/>
</bean>
<bean class="com.edu.bean.Course">
<property name="id" value="2"/>
<property name="name" value="數學"/>
</bean>
</set>
</constructor-arg>
<constructor-arg index="5">
<props>
<prop key="1">88</prop>
<prop key="2">100</prop>
</props>
</constructor-arg>
</bean>