Spring
控制反轉IOC
- 控制反轉IOC: Inversion of Control 是一種解耦設計原則 主要目的是借助第三方,比如Spring IOC容器實現具有依賴關系的對象之間的解耦,從而降低代碼之間的耦合度
- Spring IOC容器: Spring IOC容器負責創建對象并將對象連接在一起,配置這些對象.從創建中處理這些對象的整個生命周期,直到對象被完全銷毀 Spring IOC容器類似一個工廠 在創建對象時,只需要配置好配置文件或者是注解即可,不需要關注對象是如何創建的
- 控制反轉示例: 對象a依賴于對象b, 當對象a需要使用對象b時必須由對象a創建對象b的實例 引入IOC容器后,當對象a需要使用對象b時,可以指定IOC容器去創建一個對象b注入到對象a中 引入IOC容器之后,對象a獲取對象b的過程,由主動行為變為被動行為
- 實現了IOC原則的設計模式: 服務定位器模式ServiceLocator 工廠模式Factory 抽象工廠模式AbstractFactory 模板方法模式TemplateMethod 策略模式Strategy 依賴注入Depedency Inject
依賴注入DI
- 依賴注入DI: Dependency Inject 將實例變量傳入到一個對象中去 是實現控制反轉的一種設計模式
工廠設計模式Factory
- Spring框架中BeanFactory和ApplicationContext類使用工廠模式創建Bean對象
BeanFactory
- 延遲注入,即使用到某個Bean時才會進行注入
- 和ApplicationContext相比會占用更少的內存,程序啟動速度更快
ApplicationContext
- 容器啟動時就創建所有的Bean
- 和BeanFactory相比 ,BeanFactory僅提供了最基本的依賴注入支持 . ApplicationContext擴展了BeanFactory, 除了BeanFactory的功能外還包含其余更多的功能,通常使用ApplicationContext創建Bean
- ApplicationContext的三個實現類: ClassPathXmlApplication: 將上下文文件作為類路徑資源 FileSystemXmlApplication: 從文件系統中的XML文件中載入上下文定義信息 XmlWebApplicationContext: 從Web系統中的XML文件中載入上下文定義信息
單例設計模式Singleton
- Spring中的Bean的作用域默認就是單例Singleton的 . Spring中的Bean還可以定義以下作用域: prototype: 每次請求都會創建一個新的Bean實例 request: 每一次HTTP請求都會創建一個新的Bean實例,該Bean實例僅在當前HTTP request中有效 session: 每一次HTTP請求都會創建一個新的Bean實例,該Bean實例僅在當前HTTP session中有效
- Spring實現單例Bean的方式: xml的方式: <bean id="bean" class="com.oxford.Bean" scope="singleton"/> 復制代碼 注解的方式: @Scope(value="singleton") 復制代碼
- Spring底層通過ConcurrentHashMap實現單例注冊表來實現單例模式:
// 通過線程安全的concurrentHashMap實現單例注冊表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized(this.singletonObjects) {
// 檢查緩存中是否存在實例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
...
try {
singleton = singletonFactory.getObject();
}
...
// 如果實例對象不存在,則將對象注冊到單例注冊表中
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
}
復制代碼
代理設計模式Proxy
AOP中的代理模式
- 面向切面編程AOP: Aspect-Oriented Programming 面向切面編程能夠將和業務無關,但是是業務模塊中所共同調用的邏輯或者業務功能封裝起來, 比如事務管理,日志管理,權限控制等 有利于減少重復代碼,降低模塊之間的耦合度,并有利于面向未來的可拓展性和可維護性 使用AOP可以將一些通用功能抽象出來,在需要使用的地方直接使用,這樣可以大大簡化代碼量 需要增加新功能也會更加簡單方便,這樣可以提高系統的擴展性
- Spring AOP基于動態代理實現的: 代理對象實現了接口: Spring AOP會使用JAVA動態代理JDK Proxy創建代理對象 完成對象的代理操作 代理對象沒有實現接口: Spring AOP會使用Cglib Proxy生成一個被代理對象的子類作為代理類完成對象的代理操作
- Spring AOP集成了AspectJ,AspectJ是Java中最為完整的AOP框架
AspectJ和Spring AOP比較
AspectJ
- AspectJ是編譯時增強
- AspectJ基于字節碼操作Bytecode Manipluation實現
- AspectJ在切面較多的情況下要比Spring AOP的性能強很多
Spring AOP
- Spring AOP是運行時增強
- Spring AOP基于代理Proxy實現
- Spring AOP中集成了AspectJ
- Spring AOP比較簡單,在切面比較少的情況下和AspectJ的性能相似
模板方法模式TemplateMethod
- 模板方法模式: 是一種行為型模式,基于繼承的代碼復用 定義一個操作的算法骨架,將一些實現步驟延遲到子類中 模板方法使得子類可以不改變一個算法結構的情況下即可重新定義算法的某些特定步驟的實現方式
- Spring中以Template結尾的類,比如jdbcTemplate等,都是使用了模板方法模式 通常情況下,都是使用繼承來實現模板模式 在Spring中,使用了Callback與模板方法相結合的方式,既達到了代碼復用的效果,又增加了系統的靈活性
觀察者模式Observer
- 觀察者模式: 是一種對象行為模式 表示的是一種對象和對象之間具有依賴關系,當一個對象發生改變,依賴于這個對象的對象也會發生改變
- Spring事件驅動模型就是基于觀察者模式實現的 Spring事件驅動模型可以在很多應用場景中解耦代碼 比如每次添加商品時都需要更新商品索引,這時就可以使用觀察者模式
Spring事件驅動模型
- Spring事件驅動模型包含三種角色: 事件Event角色 事件監聽者Listener角色 事件發布者Publisher角色
事件角色Event
- ApplicationEvent: org.springframework.context 事件角色抽象類 繼承java.util.Event并實現了java.io.Serializable接口
- Spring中默認存在以下事件,都是繼承自ApplicationContext事件角色抽象類: ContextStartedEvent: ApplicationContext啟動后觸發的事件 ContextStoppedEvent: ApplicationContext停止后觸發的事件 ContextRefreshedEvent: ApplicationContext初始化或者刷新后觸發的事件 ContextClosedEvent: ApplicationContext關閉后觸發的事件
事件監聽者角色Listener
- ApplicationListener: 事件監聽者角色 ApplicationListener接口中定義了一個onApplicationEvent() 方法來處理ApplicationEvent. 只要實現onApplicationEvent() 方法即可完成監聽事件
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
復制代碼
事件發布者角色Publisher
- ApplicationEventPublisher: 事件發布者角色 ApplicationEventPublisher接口中定義了publishEvent() 方法來發布事件,這個方法在AbstractApplicationContext中實現 在AbstractApplicationContext中,事件是通過ApplicationEventMulticaster廣播的
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
復制代碼
Spring事件流程
- 定義一個事件: 實現一個繼承自ApplicationEvent的事件類,并寫出相應的構造函數
- 定義一個事件監聽者: 實現ApplicationListener接口 重寫onApplicationEvent() 方法
- 使用事件發布者發布消息: 使用ApplicationEventPublisher的publishEvent() 方法 重寫publishEvent() 方法發布消息
- Spring事件模型示例
適配器模式Adapter
- 適配器模式: 是結構型模式,也是各種結構型模式的起源 將一個接口轉換為調用方需要的接口 適配器使得接口不兼容的類之間可以一起工作.適配器又被稱為包裝器Wrapper
Spring AOP中的適配器模式
- Spring AOP中的增強和通知Advice使用了適配器模式,接口是AdvisorAdapter
- 常用的Advice類型包括: BeforeAdvice: 前置通知. 目標方法調用前增強 AfterAdvice: 后置通知. 目標方法調用后增強 AfterReturningAdvice: 目標方法執行結束之后 ,return之前
- 每個通知Advice都有對應的攔截器: BeforeAdvice - MethodBeforeAdviceInterceptor AfterAdvice - MethodAfterAdviceInterceptor AfterReturningAdvice - MethodAfterReturningAdviceInterceptor
- Spring中預定義的通知要通過對應的適配器,適配成為MethodInterceptor接口類型的對象
Spring MVC中的適配器模式
- Spring MVC中 ,DispatchServlet根據請求信息調用HanlderMapping, 解析請求對應的Handler, 解析到對應的Handler后,開始由HandlerAdapter適配器進行處理
- HandlerAdapter作為期望接口,具體的適配器實現類對具體目標類進行適配 .controller作為需要適配的類
- 通過使用適配器AdapterHandler可以對Spring MVC中眾多類型的Controller通過不同的方法對請求進行處理
裝飾器模式Decorator
- 裝飾器模式: 動態地給對象添加一些額外的屬性或者行為 和繼承相比,裝飾器模式更加靈活
- 裝飾器模式使用場景: 當需要修改原有的功能,但是不想直接修改原有的代碼,就可以設計一個裝飾器Decorator類在原有的代碼的外面,這樣可以在不修改原有的類的基礎上擴展新的功能
- Spring中配置DataSource時 ,DataSource可以是不同的數據庫和數據源.為了在少修改原有類的代碼下動態切換不同的數據源,這時就用到了裝飾器模式
- Spring中含有Wrapper和含有Decorator的類都用到了裝時期模式,都是動態地給一個對象添加一些額外的屬性或者功能
總結
- Spring框架中使用的設計模式:
設計模式 |
Spring框架 |
工廠模式 |
BeanFactory |
單例模式 |
Spring中的Bean |
代理模式 |
Spring AOP |
模板方法模式 |
Spring中以Template結尾的類 |
觀察者模式 |
Spring事件驅動模型 |
適配器模式 |
Spring AOP中的AdvisorAdapter |
裝飾器模式 |
Spring中含有Wrapper和含有Decorator的類 |