1.什麼是spring
- spring是一個開源框架,spring爲簡化企業級開發而生,使用spring可以使簡單的java bean 實現以前只有EJG才能實現的功能
- spring是一個IOC和AOP容器框架
2.spring的特點
- 輕量級 spring是非侵入性的 - 基於spring應用的開發中的對象可以不依賴於spring的API
- 依賴注入 DI
- 面向切面編程 AOP
- 容器 spring是一個容器,因爲它包含和管理應用對象的生命週期
- 框架 spring實現了使用簡單的組件配置組合成一個複雜的應用,在spring中可以使用xml和java註解組合這些對象
- 一站式 在IOC和AOP的基礎上可以整合各種企業應用的開源框架和優秀的第三方類庫
3 Spring容器
在Spring IOC 容器讀取bean配置、創建bean之前,必須對他進行實例化,只有在容器實例化後,才能從IOC容器裏獲取bean實例並使用它
3.1 spring提供了兩種類型的IOC容器實現
- BeanFactory: IOC容器的基本實現
- ApplicationContext: 提供了更多的高級特性,是BeanFactory的子接口
BeanFactory是Spring框架的基礎設施,面向Spring本身;ApplicationContext面向Spring框架的開發者,幾乎所有的應用場合都直接使用ApplicationContext而非底層的BeanFactory
4 IOC
4.1 什麼是IOC
IOC(Inversion of Controller)其思想是反轉資源獲取的方向,傳統的資源查找方式要求組件向容器發起請求查找資源,作爲迴應,適時得返回資源。Dog dog = new Dod();而使用了IOC之後,則是容器主動得將資源推送給他所管理的組件,組件所要做的僅是選擇一種合適的方式來接受資源,這種行爲也被稱爲查找的被動方式。
4.2 什麼是DI
DI(Dependency Injection)IOC的另一種表述方式:即組件以一些預定義好的方式(例如:setter方法),接受來自容器的資源注入,相對於IOC而言,這種表述更直接
5 Bean的配置方式
5.1 通過全類名(反射)
<bean id="person1" class="com.example.demo.bean.Person"> <property name="name" value="dong"/> <property name="age" value="12"/> </bean>
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
5.2 通過工廠方法(靜態工廠方法&實例工廠方法)
調運靜態工廠方法創建Bean是將對象創建的過程封裝到靜態方法中,當客戶端需要對象時,只需要簡單地調用靜態方法,而不用關心創建對象的細節。
要聲明通過靜態方法創建的Bean,需要在Bean的class屬性裏指定擁有該工廠的方法的類,同時在factory-method屬性裏指定工廠方法的名稱。最後,使用constrctor-arg元素爲該方法傳遞方法參數。
<bean id="simpleDateFormat" class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd hh:mm:ss"/> </bean> <bean id="date" factory-bean="simpleDateFormat" factory-method="parse"> <constructor-arg value="2018-11-11 11:11:11"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
5.3 FactoryBean
Spring中有兩種類型的Bean,一種是普通Bean,一種是工廠Bean,即FactoryBean。
工廠Bean和普通Bean不同,其返回的對象不是指定類的一個實例,其返回的是該工廠Bean的getObject方法所返回的對象
public class PersonFactoryBean implements FactoryBean<Person>{ // 返回對象 @Override public Person getObject() throws Exception { Person person = new Person(); person.setId(2); person.setName("zhu"); person.setAge(20); return person; } //返回類型 @Override public Class<?> getObjectType() { return Person.class; } //是否是單例 @Override public boolean isSingleton() { return true; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
5.4 基於註解配置
Spring能夠從classpath下自動掃描,偵測和實例化具有特定註解的Bean組件
<context:component-scan base-package="com.girhub.dge1992.bean"/>
- 1
- 1
特定組件包括:
- @Component:基本註解,表示了一個受Spring管理的Bean組件
- @Respository:標識持久層Bean組件
- @Service:標識服務層Bean組件
- @Controller:標識表現層Bean組件
自動裝配類型:
- @Autowired:根據類型自動裝配
- @Resource:註解要求提供一個Bean名稱的屬性,若該屬性爲空,則自動採用標註處的變量和方法名作爲Bean的名稱
- @Inject:和@Autowired很像,只是沒有reqired屬性
對於掃描到的組件,Spring有默認的命名策略:使用非限定類名,第一個字母小寫,也可以在註解中通過value屬性值標識組件的名稱
6 依賴注入的方式
spring支持3種依賴注入的方式
6.1 屬性注入
使用對象的set方法
<bean id="person1" class="com.github.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> </bean>
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
6.2 構造器注入
使用對象的構造函數
<bean id="person2" class="com.github.dge1992.bean.Person"> <constructor-arg value="dong" index="0" type="java.lang.String"></constructor-arg> <constructor-arg value="23" index="1" type="java.lang.Integer"></constructor-arg> </bean>
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
6.3 工廠方法注入(很少使用不推薦)
7 注入屬性值細節
7.1 字面值
可以用字符串表示的值,可以通過元素標籤或value屬性進行注入。
基本數據類型及其封裝類、String等類型都可以採用字面值注入的方式。
若字面值中包含特殊字符,可以通過<![CDATA[]]>把字面值包裹起來。 <bean id="car1" class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔馳>]]></value> </property> <property name="type" value="高檔車"/> <property name="price" value="1000"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
7.2 引用其他bean
組成應用程序的bean經常需要相互協助以完成應用程序的功能,要使bean能夠互相訪問,就必須在bean配置文件中指定對bean的引用。
在bean的配置文件中,可以通過元素或ref屬性爲bean的屬性或構造器參數指定對bean的引用。
也可以在屬性或構造器裏包含bean的聲明,這樣的bean成爲內部bean.
<bean id="car1" class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔馳>]]></value> </property> <property name="type" value="高檔車"/> <property name="price" value="1000"/> </bean> <bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="car" ref="car1"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
7.3 注入參數詳解:null和級聯屬性
可以使用專用的元素標籤爲bean的字符串或其他對象類型的屬性注入null值,spring支持級聯屬性的配置。
<bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="car" ref="car1"/> <property name="car.name" value="奔馳"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
7.4 集合屬性
在spring中可以通過一組內置的xml標籤(例如:,,)來配置集合屬性。通過指定簡單的常量值,通過指定對其他bean的引用,通過指定內置bean定義,通過指定空元素。
java.util.Map通過標籤定義,標籤裏可以使用多個作爲子標籤,普通常量使用key和value來定義,bean引用通過key-ref和value-ref屬性定義。.
使用utility scheme 定義集合
使用p命名空間,簡化xml文件的配置
<bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="cars"> <list> <bean class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔馳>]]></value> </property> <property name="type" value="高檔車"/> <property name="price" value="1000"/> </bean> <bean class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔馳111>]]></value> </property> <property name="type" value="高檔車111"/> <property name="price" value="1000111"/> </bean> </list> </property> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
集合引用外部bean
<bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="cars"> <list> <ref bean="car1"/> <ref bean="car2"/> </list> </property> <property name="names"> <list> <value>AAA</value> <value>BBB</value> </list> </property> <property name="carMap"> <map> <entry key="first" value-ref="car1"/> <entry key="second" value-ref="car2"/> </map> </property> <property name="nameMap"> <map> <entry key="firstName" value="CCC"/> <entry key="secondName" value="DDD"/> </map> </property> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
8 自動裝配
8.1 bean的自動裝配(註解注入時用到)
Spring IOC 容器可以自動配置bean,需要做的僅僅是在的autowite屬性裏指定自動裝配的模式
- byType(根據類型自動裝配)
- byName(根據名稱自動裝配)
8.2 bean自動裝配的缺點
在Bean配置文件裏設置autowire屬性進行自動裝配將會裝配bean的所有屬性。然而,若只希望裝配個別屬性時,autowire屬性就不靈活了。
autowire屬性要麼根據類型自動裝配,要麼根據名稱自動裝配,不能兩者一起使用。
9 bean之間的關係
9.1 繼承
Spring允許繼承bean的配置,被繼承的bean成爲父bean,繼承這個bean的bean成爲子bean,子bean從父bean中繼承配置,也可以覆蓋bean繼承過來的配置。
<bean id="person1" class="com.girhub.dge1992.bean.Person" p:name="dong" p:car-ref="car1"/> <bean id="person2" class="com.girhub.dge1992.bean.Person" parent="person1"/>
- 1
- 2
- 1
- 2
9.2 依賴
Spring允許用戶通過 depends-on 屬性設置 bean 前置依賴的bean,前置依賴的bean會在本bean實例化之前創建好。
<bean id="car1" class="com.girhub.dge1992.bean.Car"> <property name="name" value="寶馬"/> </bean> <bean id="person3" class="com.girhub.dge1992.bean.Person" depends-on="car1"/>
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
10 bean的作用域
在Spring中,可以在元素的scope屬性裏設置bean的作用域。
默認情況下,Spring只爲每個在IOC容器裏聲明的Bean創建唯一一個實例,整個IOC容器範圍內都能共享該實例:所有後續的getBean()調用和Bean引用都將返回這個唯一的Bean實例,該作用域被稱爲singleton,他是所有bean的默認作用域。
類別 說明 singleton 在Spring容器中僅存在一個bean實例,bean以單例是形式存在 prototype 每次調用getBean(),都會返回一個新的實例 request 每次HTTP請求都會創建一個新的實例,該作用域適用於WebApplicationContxt環境 session 同一個HTTP Session共享一個Bean,不同的HTTP Session使用不同的Bean。該作用域只適合WebApplicationContxt環境
11 使用外部屬性文件
11.1 使用外部屬性文件的好處
完成屬性值和bean的配置的分離,實現解耦
11.2 IOC容器如何引用外部文件
<context:property-placeholder location="文件路徑">
- 1
- 1
11.3 如何引用外部屬性文件的值
屬性文件一般是 *.properties 數據以key=value的形式 通過${key}獲取
12 Spring表達式語言:SpringEL
12.1 簡介
Spring表達式語言(簡稱SpEL):是一個支持運行時查詢和操作對象圖的強大的表達式語言
12.2 使用方法
使用#{…}作爲定界符
12.3 SpEL的實現
- 通過bean的id對bean進行引用
- 調用方法以及引用對象中的屬性
- 計算表達式的值
- 正則表達式的匹配
<bean id="car1" class="Car"> <property name="name" value="寶馬"/> <property name="price" value="10"/> </bean> <bean id="person1" class="Person"> <property name="name" value="dong"/> <property name="car" value="#{car1}"/> <property name="age" value="10"/> </bean> <bean id="person2" class="Person"> <property name="name" value="#{person1.name.toUpperCase()}"/> <property name="car" value="#{car1}"/> <property name="age" value="#{person1.age + 10}"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
13. bean的生命週期
Spring IOC容器可以管理Bean的生命週期,Spring允許在Bean生命週期的特定點執行定製的任務。在Bean的聲明裏設置init-method 和 destroy-method屬性,爲Bean設置初始化和銷燬方法。
Spring IOC容器對Bean的生命週期進行生命週期管理的過程:
- 通過構造器或工廠方法創建Bean實例
- 爲Bean的屬性設置值和對其他Bean的引用
- (後置處理器前置方法執行)(可選)
- 調用Bean的初始化方法
- (後置處理器後置方法執行)(可選)
- 可以使用Bean了
- 當容器關閉時,調用Bean的銷燬方法
13.1 Bean後置處理器
Bean後置處理器允許在調用初始化方法前後對Bena進行額外的處理。
Bean後置處理器對IOC容器裏的所有Bean實例逐一處理,而非單一實例,其典型作用是:檢查Bean屬性的正確性或根據特定的標準更改Bena的屬性。
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("後置處理器前置方法執行"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("後置處理器後置方法執行"); return bean; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
14. AOP
14.1 Java中的代理
代理是一種設計模式,提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象。這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操作,即擴展目標對象的功能。
14.2 Java動態代理
public class CalculateProxy { //代理對象 private Calculate calculate; public CalculateProxy(Calculate calculate) { this.calculate = calculate; } public Calculate getCalculateProxy(){ ClassLoader classLoader = Calculate.class.getClassLoader(); Class[] interfaces = {Calculate.class}; InvocationHandler handler = new InvocationHandler() { /** * * @param proxy 代理的對象 * @param method 被代理對象的方法 * @param args 方法參數 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Arrays.stream(args).forEach(e -> System.out.println("參數是:" + e)); //calculate是目標對象 Object invoke = method.invoke(calculate, args); System.out.println("結果是:" + invoke); return invoke; } }; /** * ClassLoader: 指定當前目標對象使用類加載器,獲取加載器的方法是固定的 * Class<?>[]: 目標對象實現的接口的類型,使用泛型方式確認類型 * InvocationHandler h: 事件處理,執行目標對象的方法時,會觸發事件處理器的方法, * 會把當前執行目標對象的方法作爲參數傳入 */ Calculate calculate = (Calculate) Proxy.newProxyInstance(classLoader, interfaces, handler); return calculate; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
14.3 Cglib動態代理
public class ProxyFactory implements MethodInterceptor { private Object target; public ProxyFactory(Object target) { this.target = target; } public Object getProxyInstance(){ //1.工具類 Enhancer en = new Enhancer(); //2.設置父類 en.setSuperclass(target.getClass()); //3.設置回調函數 en.setCallback(this); //4.創建子類(代理對象) return en.create(); } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("111"); Object invoke = method.invoke(target, args); System.out.println("222"); return invoke; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
14.4 AOP簡介
AOP(面向切面編程):是一種新的方法論,是對傳統OOP(面向對象編程)的補充
AOP的主要編程對象是切面,而切面模塊化橫切關注點
在應用AOP編程時,仍然需要定義公共功能,但可以明確的定義這個功能在哪裏。這樣一來橫切關注點就被模塊化到特殊的對象裏。14.5 AOP的好處
- 每個事物邏輯位於一個位置,代碼不分散,便於維護和升級
- 業務模塊更簡潔,只包含核心業務代碼
14.6 AOP術語
名稱 簡介 連接點 程序運行的某個特定位置:如類某個方法調用前、調用後、方法拋出異常後等。連接點由兩個信息確定:方法表示的程序執行點,相對點表示的位置。 切點 AOP通過切點定位到特殊的連接點。類比:連接點相當於數據庫中的記錄,切點相當於查詢條件。 切面 橫切關注點被模塊化的特殊對象。 通知 切面必須要完成的工作 目標 被通知的對象 代理 向目標對象應用通知之後創建的對象