1. 概述
-
兩大內(nèi)核:
- IoC(Inverse Of Control):反轉(zhuǎn)控制
- AOP(Aspect Oriented Programming):面向切面編程
-
優(yōu)勢:
- 方便解耦,簡化開發(fā)
- AOP編程的支持
- 聲明式事務(wù)的支持
- 方便程序的測試
- 方便集成各種優(yōu)秀的框架
- 降低JavaEE API的使用難度
- 源碼是經(jīng)典學(xué)習(xí)案例
-
體系結(jié)構(gòu):
Spring Framework Runtime
Core Container:Spring的核心容器組件, 包含了Spring框架最基本的支撐.
- Beans, 對應(yīng)spring-beans.jar. Spring進(jìn)行對象管理時依賴的jar包.
- Core, 對應(yīng)spring-core.jar, Spring核心jar包.
- Context, 對應(yīng)spring-context.jar, Spring容器上下文對象.
- SpEL, 對應(yīng)spring-expression.jar, Spring表達(dá)式語言.
耦合及解耦
程序的耦合即為程序之間的依賴關(guān)系,包括類之間的依賴和方法之間的依賴關(guān)系。其存在降低了程序的獨立性
解耦:降低程序間的依賴關(guān)系,但是并不可能做到無依賴關(guān)系。而我們要做到的程度時編譯期無依賴關(guān)系,運行期間存在依賴(也就是說編譯期對象類文件不存在不會產(chǎn)生錯誤,但在運行期會報錯)。
- 工廠模式:屬于創(chuàng)建型模式,為對象的創(chuàng)建提供了一種最佳方式。
2. IoC:
- 控制反轉(zhuǎn):將創(chuàng)建對象的控制權(quán)交給工廠。包括依賴注入和依賴查找
- 作用:降低程序的耦合程度(解除代碼中的類之間的依賴關(guān)系)
解耦的思路:- 通過反射來創(chuàng)建對象而盡量避免使用new
- 通過配置文件來獲取要創(chuàng)建的全限定類名
- 步驟:
- 獲取核心容器對象
- 根據(jù)id獲取類對象
spring中基于xml的IOC環(huán)境搭建
- 用于創(chuàng)建對象
<bean> - 用于注入數(shù)據(jù)
<property> - 用于改變作用范圍
<bean scope=""> - 和生命周期相關(guān)
<bean init-method="" destroy-method="">
ApplicationContext(開發(fā)時多使用此方法):構(gòu)建核心容器時,創(chuàng)建對象的方法時立即加載,適合單例模式。(可設(shè)置)
BeanFactory:構(gòu)建核心容器時,創(chuàng)建對象的方法時延遲加載,適合多例模式。屬于頂層接口,功能不如ApplicationContext完善。
依賴注入
使用構(gòu)造函數(shù)提供
使用set方法提供
使用注解提供
3. Spring中常用的ioc注解
用于創(chuàng)建對象:
@Component
作用:把當(dāng)前對象放入Spring容器中
屬性:value:id。默認(rèn)類名首字母改小寫
@Controller:一般用于表現(xiàn)層
@Service:一般用于業(yè)務(wù)層
@Repository:一般用于持久層
以上三個注解作用與屬性與@Component一模一樣,其能使我們更加明確三層開發(fā)模式-
用于注入數(shù)據(jù)
@Autowired
作用:- 自動按照類型注入。只要IoC容器中有唯一的一個bean對象類型和要注入的變量類型匹配,就可以注入成功。
- 如果 容器中沒有任何bean類型和要注入的匹配,則報錯。
- 如果 容器中有多個bean類型和要注入的匹配,繼續(xù)按照id配對類名查找 沒有則報錯。
@Qualifier- 作用:按照類注入的基礎(chǔ)上再按照名稱注入。給成員變量注入時需配合
@Autowired使用,給方法注入時可單獨使用。 - 屬性:value,用于指定注入bean的id。
@Resource- 作用:直接按照bean的id注入,可獨立使用
- 屬性:name,指定bean的id。
上述三個注解無法注入基本類型和String類型數(shù)據(jù),集合類型數(shù)據(jù)的注入只能通過XML來實現(xiàn)。
@Value- 作用:用于注入基本類型和String類型數(shù)據(jù)。
- 屬性:value,用于指定數(shù)據(jù)的值??墒褂肧pEL表達(dá)式
用于改變作用范圍
@Scope
作用:指定bean的作用范圍
屬性:value,指定范圍取值。singleton-單例,prototype-多例。(global-session,解決負(fù)載均衡時服務(wù)器間session共享)和生命周期相關(guān) (了解)
單例對象和多例對象不同
@PostConstruct:設(shè)置初始化方法
@PreDestroy設(shè)置銷毀方法
使用下述注解可實現(xiàn)通過配置類替換配置文件bean.xml
@Configuration:指定當(dāng)前類為一個配置類
@ComponentScan
作用:指定spring在創(chuàng)建容器時要掃描的包
屬性:value,包
@Bean
作用:把當(dāng)前方法的返回值作為bean對象存入spring的ioc容器中
屬性:name,指定bean的id
@Import
作用:導(dǎo)入其他的配置類
屬性:value,指定其他配置文件的字節(jié)碼
@PropertySource
作用:指定配置文件的名稱和路徑
屬性:value
4. AOP
- 面向切面編程:通過預(yù)編譯和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)
- 作用:將程序中重復(fù)的代碼進(jìn)行提取,在需要的時候,使用動態(tài)代理的技術(shù),在不修改源碼的情況下對已有方法實現(xiàn)增強。
5. 動態(tài)代理模式
基于接口的動態(tài)代理
基于父類的動態(tài)代理
6. 基于AOP的相關(guān)注解
配置文件:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 告知spring在創(chuàng)建容器時要掃描的包,配置所需要的標(biāo)簽不是在beans的約束中,
而是一個名為context命名空間的約束中 -->
<context:component-scan base-package="com.handsomexu"></context:component-scan>
<!-- 使能aop -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
@Aspect:表示切面
通知:
前置通知:@Before
后置通知:@After Returning
異常通知:@After Throwing
最終通知:@After
環(huán)繞通知:@Around
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
@Around("com.xyz.myapp.CommonPointcuts.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}
在注解配置模式的aop使用中,spring對通知的調(diào)用順序可能會出現(xiàn)錯誤的bug,建議采用環(huán)繞通知來進(jìn)行動態(tài)代理模式的配置
