Spring必知必會,底層都使用了哪些設(shè)計模式?
Spring用到的設(shè)計模式
1
代理模式:最常見的 AOP 的實現(xiàn)方式就是通過代理來實現(xiàn),Spring主要是使用 JDK 動態(tài)代理和 CGLIB 代理。
其中JDK代理實現(xiàn)代碼如下所示:
public class ProxyHandler implements InvocationHandler {Object target;public ProxyHandler(Object target) {this.target=target;}public void before(String param) throws Throwable {if(!param.equals("magicalwolf"))throw new IllegalArgumentException();}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {before((String)args[0]);return method.invoke(target, args);}}public class Main {public static void main(String[] args) {Subject target=new RealSubject();Subject proxy=(Subject)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new ProxyHandler(target));proxy.request("magicalwolf");proxy.request("hello");}}
CGLIB代理實現(xiàn)如下:
public class RequestInterceptor implements MethodInterceptor {public void before(String param) throws Throwable {if(!param.equals("hello"))throw new IllegalArgumentException();}public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {before((String)args[0]);return proxy.invokeSuper(obj, args);//調(diào)用父類的方法}}public class Main {public static void main(String[] args) {Enhancer enhancer = new Enhancer(); //字節(jié)碼增強器enhancer.setSuperclass(RealSubject.class); //代理類enhancer.setCallback(new RequestInterceptor());//回調(diào)方法Subject proxy = (Subject) enhancer.create();proxy.request("hello");}}
2
模版模式:定義了一個在操作中的算法框架,而將一些具體步驟延遲到子類中,使子類看可以在不改變算法結(jié)構(gòu)下即可重新定義該算法的某些特定步驟。
主要是一些對數(shù)據(jù)庫操作的類用到,比如 JdbcTemplate、JpaTemplate,因為查詢數(shù)據(jù)庫的建立連接、執(zhí)行查詢、關(guān)閉連接幾個過程,非常適用于模板方法。
//提交事務(wù)protected abstract void doCommit(DefaultTransactionStatus status);//回滾事務(wù)protected abstract void doRollback(DefaultTransactionStatus status);//開始事務(wù)protected abstract void doBegin(Object transaction, TransactionDefinition definition)//獲取當(dāng)前的事務(wù)對象protected abstract Object doGetTransaction()
Spring框架啟動也遵循如準(zhǔn)備啟動上下文,初始化BeanFactory、BeanFactory對象的前置處理與注冊,消息發(fā)送器初始化,發(fā)送應(yīng)用啟動消息等等特定的特定啟動流程,將BeanFactory的初始化和刷新留在了具體的應(yīng)用實現(xiàn)類去實現(xiàn)。
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {public void refresh() throws BeansException, IllegalStateException {prepareRefresh();//子類實現(xiàn)初始化BeanFactory對象ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory);registerBeanPostProcessors(beanFactory);initMessageSource();initApplicationEventMulticaster();onRefresh();registerListeners();finishBeanFactoryInitialization(beanFactory);finishRefresh();}protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();}// 兩個抽象方法public abstract ConfigurableListableBeanFactory getBeanFactory()throws IllegalStateException;protected abstract void refreshBeanFactory()throws BeansException, IllegalStateException;}
3
工廠模式:定義了用于創(chuàng)建對象的接口,讓子類決定要創(chuàng)建哪個類的實例化,可以促進組件或類之間的松耦合,通過使用接口而不是將特定的類綁定到應(yīng)用程序代碼中。
Spring框架使用工廠模式實現(xiàn)了 BeanFactory 和 ApplicationContext 接口,基于工廠模式為Spring應(yīng)用程序創(chuàng)建Bean,并管理著每一個Bean的生命周期。如BeanFactory實例中的doGetBean方法可以根據(jù)使用者傳入的名字,類型,參數(shù)等生成對象并返回。
public class StaticListableBeanFactory implements ListableBeanFactory {private final Map<String, Object> beans;protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly)throws BeansException {String beanName = transformedBeanName(name);Object beanInstance;Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}}
4
單例模式:保證了一個類僅有的一個實例,并提供了一個訪問它的全局訪問點,提供控制器對關(guān)鍵類的訪問。
單例模式如DB的連接類或Hibernate中的SessionFactory類,節(jié)省了大量的內(nèi)存,Spring框架中的Bean對象默認(rèn)都是為單例,在Bean對象注冊器實例上使用了Map來管理Bean對象,每次獲取到的對象是從該單例容器中取出來的。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}}
5
責(zé)任鏈可以避免發(fā)送者與請求者耦合在一起,讓多個對象都有可能接收到請求,將這些對象連接成一條鏈,并且沿著這條鏈路傳遞請求,直到有對象處理為止。
Spring中的Filter實現(xiàn)了責(zé)任鏈模式,管理者所有的Filter的順序執(zhí)行,可以對同一種對象資源實現(xiàn)不同業(yè)務(wù)場景的處理,達到業(yè)務(wù)解耦。詳情可參考以下鏈接。
public final class ApplicationFilterChain implements FilterChain {private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];private int pos = 0;private int n = 0;public void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException {internalDoFilter(request,response);}private void internalDoFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException {if (pos < n) {ApplicationFilterConfig filterConfig = filters[pos++];Filter filter = filterConfig.getFilter();filter.doFilter(request, response, this);}}}
6
觀察者模式: 定義了對象之間一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都能得到通知并自動更新。
在Spring框架中,觀察者用于實現(xiàn)ApplicationContext的事件處理功能,為開發(fā)者提供了ApplicationEvent和ApplicationLIstneter接口來啟用事件處理,任何Bean實現(xiàn)了SpringListner接口都會收到ApplicationEvent作為事件發(fā)布者推送的消息。更多詳情可參考以下鏈接。
public class PublishService {private ApplicationContext applicationContext;public void publishEvent() {applicationContext.publishEvent(new TestSuccessEvent(this));}}public class ListenService {(TestSuccessEvent.class)public void test() {....}}public class AsyncEventConfig {(name = "applicationEventMulticaster")public ApplicationEventMulticaster simpleApplicationEventMulticaster() {SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());return eventMulticaster;}}public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {.....public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));Executor executor = getTaskExecutor();for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}.....}
7
適配器模式:將一個類的接口轉(zhuǎn)換成希望的另外一個接口,Spring框架使用適配器模式實現(xiàn)了很多功能,常見的適配器模式的類有 配置適配器RequestMappinghandlerAdapter完成了從請求到方法的映射,返回值到對應(yīng)的視圖或頁面的適配轉(zhuǎn)換。
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {public RequestMappingHandlerAdapter requestMappingHandlerAdapter(ContentNegotiationManager contentNegotiationManager,FormattingConversionService conversionService,Validator validator) {RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();.....return adapter;}}public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {protected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ModelAndView mav;checkRequest(request);if (this.synchronizeOnSession) {HttpSession session = request.getSession(false);if (session != null) {Object mutex = WebUtils.getSessionMutex(session);synchronized (mutex) {mav = invokeHandlerMethod(request, response, handlerMethod);}}else {mav = invokeHandlerMethod(request, response, handlerMethod);}}else {mav = invokeHandlerMethod(request, response, handlerMethod);}if (!response.containsHeader(HEADER_CACHE_CONTROL)) {if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);}else {prepareResponse(response);}}return mav;}}
8
建造者模式: 可以一步步構(gòu)建一個復(fù)雜的對象,最終將返回完整的對象,對象創(chuàng)建的邏輯和過程是通用的,使用它來創(chuàng)建相同的類型的不同具體實現(xiàn),隱藏了調(diào)用方調(diào)用代碼時構(gòu)建對象的細節(jié)。
Spring框架中有一些功能實現(xiàn)了建造者模式如EmbeddedDatabaseBuilder、BeanDefinitionBuilder、MockMvcWebClientBuilder等。
public class EmbeddedDatabaseBuilder {......public EmbeddedDatabaseBuilder setName(String databaseName) {this.databaseFactory.setDatabaseName(databaseName);return this;}public EmbeddedDatabaseBuilder setType(EmbeddedDatabaseType databaseType) {this.databaseFactory.setDatabaseType(databaseType);return this;}public EmbeddedDatabaseBuilder setDataSourceFactory(DataSourceFactory dataSourceFactory) {Assert.notNull(dataSourceFactory, "DataSourceFactory is required");this.databaseFactory.setDataSourceFactory(dataSourceFactory);return this;}......}
IOC和AOP的理解
IOC 叫做控制反轉(zhuǎn)。指的是通過Spring來管理對象的創(chuàng)建、配置和生命周期,這樣相當(dāng)于把控制權(quán)交給了Spring,不需要人工來管理對象之間復(fù)雜的依賴關(guān)系,這樣做的好處就是解耦。
在Spring里面,主要提供了 BeanFactory 和 ApplicationContext 兩種 IOC 容器。
AOP 叫做面向切面編程。是一個編程范式,目的就是提高代碼的模塊性。
Spring AOP 基于動態(tài)代理的方式實現(xiàn),如果是實現(xiàn)了接口的話就會使用 JDK 動態(tài)代理,反之則使用 CGLIB 代理。
Spring中, AOP 的應(yīng)用主要體現(xiàn)在事務(wù)、日志、異常處理等方面,通過在代碼的前后做一些增強處理,可以實現(xiàn)對業(yè)務(wù)邏輯的隔離,提高代碼的模塊化能力,同時也是解耦。Spring主要提供了 Aspect 切面、JoinPoint 連接點、PointCut 切入點、Advice 增強等實現(xiàn)方式。
幾種代理方式的實現(xiàn)方式與區(qū)別

Spring必知必會上篇完,下篇內(nèi)容預(yù)告:
Spring AOP 和 AspectJ AOP 有什么區(qū)別?
5.Spring框架的主要模塊
Bean的生命周期
……
……
更多干貨請點擊關(guān)注
▼
