Spring必知必會(huì),底層都使用了哪些設(shè)計(jì)模式?
Spring用到的設(shè)計(jì)模式
1
代理模式:最常見的 AOP 的實(shí)現(xiàn)方式就是通過(guò)代理來(lái)實(shí)現(xiàn),Spring主要是使用 JDK 動(dòng)態(tài)代理和 CGLIB 代理。
其中JDK代理實(shí)現(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代理實(shí)現(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é)碼增強(qiáng)器enhancer.setSuperclass(RealSubject.class); //代理類enhancer.setCallback(new RequestInterceptor());//回調(diào)方法Subject proxy = (Subject) enhancer.create();proxy.request("hello");}}
2
模版模式:定義了一個(gè)在操作中的算法框架,而將一些具體步驟延遲到子類中,使子類看可以在不改變算法結(jié)構(gòu)下即可重新定義該算法的某些特定步驟。
主要是一些對(duì)數(shù)據(jù)庫(kù)操作的類用到,比如 JdbcTemplate、JpaTemplate,因?yàn)椴樵償?shù)據(jù)庫(kù)的建立連接、執(zhí)行查詢、關(guān)閉連接幾個(gè)過(guò)程,非常適用于模板方法。
//提交事務(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ù)對(duì)象protected abstract Object doGetTransaction()
Spring框架啟動(dòng)也遵循如準(zhǔn)備啟動(dòng)上下文,初始化BeanFactory、BeanFactory對(duì)象的前置處理與注冊(cè),消息發(fā)送器初始化,發(fā)送應(yīng)用啟動(dòng)消息等等特定的特定啟動(dòng)流程,將BeanFactory的初始化和刷新留在了具體的應(yīng)用實(shí)現(xiàn)類去實(shí)現(xiàn)。
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {public void refresh() throws BeansException, IllegalStateException {prepareRefresh();//子類實(shí)現(xiàn)初始化BeanFactory對(duì)象ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory);registerBeanPostProcessors(beanFactory);initMessageSource();initApplicationEventMulticaster();onRefresh();registerListeners();finishBeanFactoryInitialization(beanFactory);finishRefresh();}protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();}// 兩個(gè)抽象方法public abstract ConfigurableListableBeanFactory getBeanFactory()throws IllegalStateException;protected abstract void refreshBeanFactory()throws BeansException, IllegalStateException;}
3
工廠模式:定義了用于創(chuàng)建對(duì)象的接口,讓子類決定要?jiǎng)?chuàng)建哪個(gè)類的實(shí)例化,可以促進(jìn)組件或類之間的松耦合,通過(guò)使用接口而不是將特定的類綁定到應(yīng)用程序代碼中。
Spring框架使用工廠模式實(shí)現(xiàn)了 BeanFactory 和 ApplicationContext 接口,基于工廠模式為Spring應(yīng)用程序創(chuàng)建Bean,并管理著每一個(gè)Bean的生命周期。如BeanFactory實(shí)例中的doGetBean方法可以根據(jù)使用者傳入的名字,類型,參數(shù)等生成對(duì)象并返回。
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
單例模式:保證了一個(gè)類僅有的一個(gè)實(shí)例,并提供了一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn),提供控制器對(duì)關(guān)鍵類的訪問(wèn)。
單例模式如DB的連接類或Hibernate中的SessionFactory類,節(jié)省了大量的內(nèi)存,Spring框架中的Bean對(duì)象默認(rèn)都是為單例,在Bean對(duì)象注冊(cè)器實(shí)例上使用了Map來(lái)管理Bean對(duì)象,每次獲取到的對(duì)象是從該單例容器中取出來(lái)的。
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ā)送者與請(qǐng)求者耦合在一起,讓多個(gè)對(duì)象都有可能接收到請(qǐng)求,將這些對(duì)象連接成一條鏈,并且沿著這條鏈路傳遞請(qǐng)求,直到有對(duì)象處理為止。
Spring中的Filter實(shí)現(xiàn)了責(zé)任鏈模式,管理者所有的Filter的順序執(zhí)行,可以對(duì)同一種對(duì)象資源實(shí)現(xiàn)不同業(yè)務(wù)場(chǎng)景的處理,達(dá)到業(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
觀察者模式: 定義了對(duì)象之間一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都能得到通知并自動(dòng)更新。
在Spring框架中,觀察者用于實(shí)現(xiàn)ApplicationContext的事件處理功能,為開發(fā)者提供了ApplicationEvent和ApplicationLIstneter接口來(lái)啟用事件處理,任何Bean實(shí)現(xiàn)了SpringListner接口都會(huì)收到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
適配器模式:將一個(gè)類的接口轉(zhuǎn)換成希望的另外一個(gè)接口,Spring框架使用適配器模式實(shí)現(xiàn)了很多功能,常見的適配器模式的類有 配置適配器RequestMappinghandlerAdapter完成了從請(qǐng)求到方法的映射,返回值到對(duì)應(yīng)的視圖或頁(yè)面的適配轉(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)建一個(gè)復(fù)雜的對(duì)象,最終將返回完整的對(duì)象,對(duì)象創(chuàng)建的邏輯和過(guò)程是通用的,使用它來(lái)創(chuàng)建相同的類型的不同具體實(shí)現(xiàn),隱藏了調(diào)用方調(diào)用代碼時(shí)構(gòu)建對(duì)象的細(xì)節(jié)。
Spring框架中有一些功能實(shí)現(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)。指的是通過(guò)Spring來(lái)管理對(duì)象的創(chuàng)建、配置和生命周期,這樣相當(dāng)于把控制權(quán)交給了Spring,不需要人工來(lái)管理對(duì)象之間復(fù)雜的依賴關(guān)系,這樣做的好處就是解耦。
在Spring里面,主要提供了 BeanFactory 和 ApplicationContext 兩種 IOC 容器。
AOP 叫做面向切面編程。是一個(gè)編程范式,目的就是提高代碼的模塊性。
Spring AOP 基于動(dòng)態(tài)代理的方式實(shí)現(xiàn),如果是實(shí)現(xiàn)了接口的話就會(huì)使用 JDK 動(dòng)態(tài)代理,反之則使用 CGLIB 代理。
Spring中, AOP 的應(yīng)用主要體現(xiàn)在事務(wù)、日志、異常處理等方面,通過(guò)在代碼的前后做一些增強(qiáng)處理,可以實(shí)現(xiàn)對(duì)業(yè)務(wù)邏輯的隔離,提高代碼的模塊化能力,同時(shí)也是解耦。Spring主要提供了 Aspect 切面、JoinPoint 連接點(diǎn)、PointCut 切入點(diǎn)、Advice 增強(qiáng)等實(shí)現(xiàn)方式。
幾種代理方式的實(shí)現(xiàn)方式與區(qū)別

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