<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring 中經(jīng)典的 9 種設(shè)計(jì)模式,打死也要記住?。?/h1>

          共 9794字,需瀏覽 20分鐘

           ·

          2021-11-09 20:07

          程序員的成長(zhǎng)之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
          關(guān)注


          閱讀本文大概需要 9 分鐘。

          來(lái)自:https://blog.csdn.net/caoxiaohong1005

          Spring中涉及的設(shè)計(jì)模式總結(jié)

          1.簡(jiǎn)單工廠(chǎng)(非23種設(shè)計(jì)模式中的一種)

          實(shí)現(xiàn)方式:

          BeanFactory。Spring中的BeanFactory就是簡(jiǎn)單工廠(chǎng)模式的體現(xiàn),根據(jù)傳入一個(gè)唯一的標(biāo)識(shí)來(lái)獲得Bean對(duì)象,但是否是在傳入?yún)?shù)后創(chuàng)建還是傳入?yún)?shù)前創(chuàng)建這個(gè)要根據(jù)具體情況來(lái)定。

          實(shí)質(zhì):

          由一個(gè)工廠(chǎng)類(lèi)根據(jù)傳入的參數(shù),動(dòng)態(tài)決定應(yīng)該創(chuàng)建哪一個(gè)產(chǎn)品類(lèi)。

          實(shí)現(xiàn)原理:

          bean容器的啟動(dòng)階段:
          • 讀取bean的xml配置文件,將bean元素分別轉(zhuǎn)換成一個(gè)BeanDefinition對(duì)象。

          • 然后通過(guò)BeanDefinitionRegistry將這些bean注冊(cè)到beanFactory中,保存在它的一個(gè)ConcurrentHashMap中。

          • 將BeanDefinition注冊(cè)到了beanFactory之后,在這里Spring為我們提供了一個(gè)擴(kuò)展的切口,允許我們通過(guò)實(shí)現(xiàn)接口BeanFactoryPostProcessor 在此處來(lái)插入我們定義的代碼。

            典型的例子就是:PropertyPlaceholderConfigurer,我們一般在配置數(shù)據(jù)庫(kù)的dataSource時(shí)使用到的占位符的值,就是它注入進(jìn)去的。

          容器中bean的實(shí)例化階段:
          實(shí)例化階段主要是通過(guò)反射或者CGLIB對(duì)bean進(jìn)行實(shí)例化,在這個(gè)階段Spring又給我們暴露了很多的擴(kuò)展點(diǎn):
          • 各種的Aware接口?,比如 BeanFactoryAware,對(duì)于實(shí)現(xiàn)了這些Aware接口的bean,在實(shí)例化bean時(shí)Spring會(huì)幫我們注入對(duì)應(yīng)的BeanFactory的實(shí)例。
          • BeanPostProcessor接口?,實(shí)現(xiàn)了BeanPostProcessor接口的bean,在實(shí)例化bean時(shí)Spring會(huì)幫我們調(diào)用接口中的方法。
          • InitializingBean接口?,實(shí)現(xiàn)了InitializingBean接口的bean,在實(shí)例化bean時(shí)Spring會(huì)幫我們調(diào)用接口中的方法。
          • DisposableBean接口?,實(shí)現(xiàn)了BeanPostProcessor接口的bean,在該bean死亡時(shí)Spring會(huì)幫我們調(diào)用接口中的方法。

          設(shè)計(jì)意義:

          松耦合。?可以將原來(lái)硬編碼的依賴(lài),通過(guò)Spring這個(gè)beanFactory這個(gè)工廠(chǎng)來(lái)注入依賴(lài),也就是說(shuō)原來(lái)只有依賴(lài)方和被依賴(lài)方,現(xiàn)在我們引入了第三方——spring這個(gè)beanFactory,由它來(lái)解決bean之間的依賴(lài)問(wèn)題,達(dá)到了松耦合的效果.
          bean的額外處理。?通過(guò)Spring接口的暴露,在實(shí)例化bean的階段我們可以進(jìn)行一些額外的處理,這些額外的處理只需要讓bean實(shí)現(xiàn)對(duì)應(yīng)的接口即可,那么spring就會(huì)在bean的生命周期調(diào)用我們實(shí)現(xiàn)的接口來(lái)處理該bean。[非常重要]
          推薦下自己做的 Spring Boot 的實(shí)戰(zhàn)項(xiàng)目:
          https://github.com/YunaiV/ruoyi-vue-pro

          2.工廠(chǎng)方法

          實(shí)現(xiàn)方式:

          FactoryBean接口。

          實(shí)現(xiàn)原理:

          實(shí)現(xiàn)了FactoryBean接口的bean是一類(lèi)叫做factory的bean。其特點(diǎn)是,spring會(huì)在使用getBean()調(diào)用獲得該bean時(shí),會(huì)自動(dòng)調(diào)用該bean的getObject()方法,所以返回的不是factory這個(gè)bean,而是這個(gè)bean.getOjbect()方法的返回值。

          例子:

          典型的例子有spring與mybatis的結(jié)合。
          代碼示例:
          說(shuō)明:
          我們看上面該bean,因?yàn)閷?shí)現(xiàn)了FactoryBean接口,所以返回的不是 SqlSessionFactoryBean 的實(shí)例,而是它的 SqlSessionFactoryBean.getObject() 的返回值。
          推薦下自己做的 Spring Cloud 的實(shí)戰(zhàn)項(xiàng)目:
          https://github.com/YunaiV/onemall

          3.單例模式

          Spring依賴(lài)注入Bean實(shí)例默認(rèn)是單例的。
          Spring的依賴(lài)注入(包括lazy-init方式)都是發(fā)生在AbstractBeanFactory的getBean里。getBean的doGetBean方法調(diào)用getSingleton進(jìn)行bean的創(chuàng)建。
          分析getSingleton()方法

          public?Object?getSingleton(String?beanName){
          ????//參數(shù)true設(shè)置標(biāo)識(shí)允許早期依賴(lài)
          ????return?getSingleton(beanName,true);
          }
          protected?Object?getSingleton(String?beanName,?boolean?allowEarlyReference)?{
          ????//檢查緩存中是否存在實(shí)例
          ????Object?singletonObject?=?this.singletonObjects.get(beanName);
          ????if?(singletonObject?==?null?&&?isSingletonCurrentlyInCreation(beanName))?{
          ????????//如果為空,則鎖定全局變量并進(jìn)行處理。
          ????????synchronized?(this.singletonObjects)?{
          ????????????//如果此bean正在加載,則不處理
          ????????????singletonObject?=?this.earlySingletonObjects.get(beanName);
          ????????????if?(singletonObject?==?null?&&?allowEarlyReference)?{
          ????????????????//當(dāng)某些方法需要提前初始化的時(shí)候則會(huì)調(diào)用addSingleFactory?方法將對(duì)應(yīng)的ObjectFactory初始化策略存儲(chǔ)在singletonFactories
          ????????????????ObjectFactory?singletonFactory?=?this.singletonFactories.get(beanName);
          ????????????????if?(singletonFactory?!=?null)?{
          ????????????????????//調(diào)用預(yù)先設(shè)定的getObject方法
          ????????????????????singletonObject?=?singletonFactory.getObject();
          ????????????????????//記錄在緩存中,earlysingletonObjects和singletonFactories互斥
          ????????????????????this.earlySingletonObjects.put(beanName,?singletonObject);
          ????????????????????this.singletonFactories.remove(beanName);
          ????????????????}
          ????????????}
          ????????}
          ????}
          ????return?(singletonObject?!=?NULL_OBJECT???singletonObject?:?null);
          }

          getSingleton()過(guò)程圖
          ps:spring依賴(lài)注入時(shí),使用了 雙重判斷加鎖 的單例模式
          總結(jié)
          單例模式定義:?保證一個(gè)類(lèi)僅有一個(gè)實(shí)例,并提供一個(gè)訪(fǎng)問(wèn)它的全局訪(fǎng)問(wèn)點(diǎn)。
          spring對(duì)單例的實(shí)現(xiàn):?spring中的單例模式完成了后半句話(huà),即提供了全局的訪(fǎng)問(wèn)點(diǎn)BeanFactory。但沒(méi)有從構(gòu)造器級(jí)別去控制單例,這是因?yàn)閟pring管理的是任意的java對(duì)象。

          4.適配器模式

          實(shí)現(xiàn)方式:

          SpringMVC中的適配器HandlerAdatper。

          實(shí)現(xiàn)原理:

          HandlerAdatper根據(jù)Handler規(guī)則執(zhí)行不同的Handler。

          實(shí)現(xiàn)過(guò)程:

          DispatcherServlet根據(jù)HandlerMapping返回的handler,向HandlerAdatper發(fā)起請(qǐng)求,處理Handler。
          HandlerAdapter根據(jù)規(guī)則找到對(duì)應(yīng)的Handler并讓其執(zhí)行,執(zhí)行完畢后Handler會(huì)向HandlerAdapter返回一個(gè)ModelAndView,最后由HandlerAdapter向DispatchServelet返回一個(gè)ModelAndView。

          實(shí)現(xiàn)意義:

          HandlerAdatper使得Handler的擴(kuò)展變得容易,只需要增加一個(gè)新的Handler和一個(gè)對(duì)應(yīng)的HandlerAdapter即可。
          因此Spring定義了一個(gè)適配接口,使得每一種Controller有一種對(duì)應(yīng)的適配器實(shí)現(xiàn)類(lèi),讓適配器代替controller執(zhí)行相應(yīng)的方法。這樣在擴(kuò)展Controller時(shí),只需要增加一個(gè)適配器類(lèi)就完成了SpringMVC的擴(kuò)展了。

          5.裝飾器模式

          實(shí)現(xiàn)方式:

          Spring中用到的包裝器模式在類(lèi)名上有兩種表現(xiàn):一種是類(lèi)名中含有Wrapper,另一種是類(lèi)名中含有Decorator。

          實(shí)質(zhì):

          動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。
          就增加功能來(lái)說(shuō),Decorator模式相比生成子類(lèi)更為靈活。

          6.代理模式

          實(shí)現(xiàn)方式:

          AOP底層,就是動(dòng)態(tài)代理模式的實(shí)現(xiàn)。

          動(dòng)態(tài)代理:

          在內(nèi)存中構(gòu)建的,不需要手動(dòng)編寫(xiě)代理類(lèi)

          靜態(tài)代理:

          需要手工編寫(xiě)代理類(lèi),代理類(lèi)引用被代理對(duì)象。

          實(shí)現(xiàn)原理:

          切面在應(yīng)用運(yùn)行的時(shí)刻被織入。一般情況下,在織入切面時(shí),AOP容器會(huì)為目標(biāo)對(duì)象創(chuàng)建動(dòng)態(tài)的創(chuàng)建一個(gè)代理對(duì)象。SpringAOP就是以這種方式織入切面的。
          織入:把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過(guò)程。

          7.觀察者模式

          實(shí)現(xiàn)方式:

          spring的事件驅(qū)動(dòng)模型使用的是 觀察者模式 ,Spring中Observer模式常用的地方是listener的實(shí)現(xiàn)。

          具體實(shí)現(xiàn):

          事件機(jī)制的實(shí)現(xiàn)需要三個(gè)部分,事件源,事件,事件監(jiān)聽(tīng)器
          ApplicationEvent抽象類(lèi)[事件]
          繼承自jdk的EventObject,所有的事件都需要繼承ApplicationEvent,并且通過(guò)構(gòu)造器參數(shù)source得到事件源.
          該類(lèi)的實(shí)現(xiàn)類(lèi)ApplicationContextEvent表示ApplicaitonContext的容器事件.
          代碼:

          public?abstract?class?ApplicationEvent?extends?EventObject?{
          ????private?static?final?long?serialVersionUID?=?7099057708183571937L;
          ????private?final?long?timestamp;
          ????public?ApplicationEvent(Object?source)?{
          ????super(source);
          ????this.timestamp?=?System.currentTimeMillis();
          ????}
          ????public?final?long?getTimestamp()?{
          ????????return?this.timestamp;
          ????}
          }

          ApplicationListener接口[事件監(jiān)聽(tīng)器]
          繼承自jdk的EventListener,所有的監(jiān)聽(tīng)器都要實(shí)現(xiàn)這個(gè)接口。
          這個(gè)接口只有一個(gè)onApplicationEvent()方法,該方法接受一個(gè)ApplicationEvent或其子類(lèi)對(duì)象作為參數(shù),在方法體中,可以通過(guò)不同對(duì)Event類(lèi)的判斷來(lái)進(jìn)行相應(yīng)的處理。
          當(dāng)事件觸發(fā)時(shí)所有的監(jiān)聽(tīng)器都會(huì)收到消息。
          代碼:

          public?interface?ApplicationListener<E?extends?ApplicationEvent>?extends?EventListener?{
          ?????void?onApplicationEvent(E?event);
          }

          ApplicationContext接口[事件源]
          ApplicationContext是spring中的全局容器,翻譯過(guò)來(lái)是”應(yīng)用上下文”。
          實(shí)現(xiàn)了ApplicationEventPublisher接口。

          職責(zé):

          負(fù)責(zé)讀取bean的配置文檔,管理bean的加載,維護(hù)bean之間的依賴(lài)關(guān)系,可以說(shuō)是負(fù)責(zé)bean的整個(gè)生命周期,再通俗一點(diǎn)就是我們平時(shí)所說(shuō)的IOC容器。
          代碼:

          public?interface?ApplicationEventPublisher?{
          ????????void?publishEvent(ApplicationEvent?event);
          }

          public?void?publishEvent(ApplicationEvent?event)?{
          ????Assert.notNull(event,?"Event?must?not?be?null");
          ????if?(logger.isTraceEnabled())?{
          ?????????logger.trace("Publishing?event?in?"?+?getDisplayName()?+?":?"?+?event);
          ????}
          ????getApplicationEventMulticaster().multicastEvent(event);
          ????if?(this.parent?!=?null)?{
          ????this.parent.publishEvent(event);
          ????}
          }

          ApplicationEventMulticaster抽象類(lèi)[事件源中publishEvent方法需要調(diào)用其方法getApplicationEventMulticaster]
          屬于事件廣播器,它的作用是把Applicationcontext發(fā)布的Event廣播給所有的監(jiān)聽(tīng)器.
          代碼:

          public?abstract?class?AbstractApplicationContext?extends?DefaultResourceLoader
          ????implements?ConfigurableApplicationContext,?DisposableBean?
          {
          ????private?ApplicationEventMulticaster?applicationEventMulticaster;
          ????protected?void?registerListeners()?{
          ????//?Register?statically?specified?listeners?first.
          ????for?(ApplicationListener?listener?:?getApplicationListeners())?{
          ????getApplicationEventMulticaster().addApplicationListener(listener);
          ????}
          ????//?Do?not?initialize?FactoryBeans?here:?We?need?to?leave?all?regular?beans
          ????//?uninitialized?to?let?post-processors?apply?to?them!
          ????String[]?listenerBeanNames?=?getBeanNamesForType(ApplicationListener.class,?true,?false);
          ????for?(String?lisName?:?listenerBeanNames)?{
          ????getApplicationEventMulticaster().addApplicationListenerBean(lisName);
          ????}
          ??}
          }

          8.策略模式

          實(shí)現(xiàn)方式:

          Spring框架的資源訪(fǎng)問(wèn)Resource接口。該接口提供了更強(qiáng)的資源訪(fǎng)問(wèn)能力,Spring 框架本身大量使用了 Resource 接口來(lái)訪(fǎng)問(wèn)底層資源。

          Resource 接口介紹

          source 接口是具體資源訪(fǎng)問(wèn)策略的抽象,也是所有資源訪(fǎng)問(wèn)類(lèi)所實(shí)現(xiàn)的接口。
          Resource 接口主要提供了如下幾個(gè)方法:
          • getInputStream():?定位并打開(kāi)資源,返回資源對(duì)應(yīng)的輸入流。每次調(diào)用都返回新的輸入流。調(diào)用者必須負(fù)責(zé)關(guān)閉輸入流。
          • exists():?返回 Resource 所指向的資源是否存在。
          • isOpen():?返回資源文件是否打開(kāi),如果資源文件不能多次讀取,每次讀取結(jié)束應(yīng)該顯式關(guān)閉,以防止資源泄漏。
          • getDescription():?返回資源的描述信息,通常用于資源處理出錯(cuò)時(shí)輸出該信息,通常是全限定文件名或?qū)嶋H URL。
          • getFile:?返回資源對(duì)應(yīng)的 File 對(duì)象。
          • getURL:?返回資源對(duì)應(yīng)的 URL 對(duì)象。
          最后兩個(gè)方法通常無(wú)須使用,僅在通過(guò)簡(jiǎn)單方式訪(fǎng)問(wèn)無(wú)法實(shí)現(xiàn)時(shí),Resource 提供傳統(tǒng)的資源訪(fǎng)問(wèn)的功能。
          Resource 接口本身沒(méi)有提供訪(fǎng)問(wèn)任何底層資源的實(shí)現(xiàn)邏輯,針對(duì)不同的底層資源,Spring 將會(huì)提供不同的 Resource 實(shí)現(xiàn)類(lèi),不同的實(shí)現(xiàn)類(lèi)負(fù)責(zé)不同的資源訪(fǎng)問(wèn)邏輯。
          Spring 為 Resource 接口提供了如下實(shí)現(xiàn)類(lèi):
          • UrlResource:?訪(fǎng)問(wèn)網(wǎng)絡(luò)資源的實(shí)現(xiàn)類(lèi)。
          • ClassPathResource:?訪(fǎng)問(wèn)類(lèi)加載路徑里資源的實(shí)現(xiàn)類(lèi)。
          • FileSystemResource:?訪(fǎng)問(wèn)文件系統(tǒng)里資源的實(shí)現(xiàn)類(lèi)。
          • ServletContextResource:?訪(fǎng)問(wèn)相對(duì)于 ServletContext 路徑里的資源的實(shí)現(xiàn)類(lèi).
          • InputStreamResource:?訪(fǎng)問(wèn)輸入流資源的實(shí)現(xiàn)類(lèi)。
          • ByteArrayResource:?訪(fǎng)問(wèn)字節(jié)數(shù)組資源的實(shí)現(xiàn)類(lèi)。
          這些 Resource 實(shí)現(xiàn)類(lèi),針對(duì)不同的的底層資源,提供了相應(yīng)的資源訪(fǎng)問(wèn)邏輯,并提供便捷的包裝,以利于客戶(hù)端程序的資源訪(fǎng)問(wèn)。

          9.模版方法模式

          經(jīng)典模板方法定義:

          父類(lèi)定義了骨架(調(diào)用哪些方法及順序),某些特定方法由子類(lèi)實(shí)現(xiàn)。
          最大的好處:代碼復(fù)用,減少重復(fù)代碼。除了子類(lèi)要實(shí)現(xiàn)的特定方法,其他方法及方法調(diào)用順序都在父類(lèi)中預(yù)先寫(xiě)好了。
          所以父類(lèi)模板方法中有兩類(lèi)方法:
          共同的方法:?所有子類(lèi)都會(huì)用到的代碼
          不同的方法:?子類(lèi)要覆蓋的方法,分為兩種:
          • 抽象方法:父類(lèi)中的是抽象方法,子類(lèi)必須覆蓋
          • 鉤子方法:父類(lèi)中是一個(gè)空方法,子類(lèi)繼承了默認(rèn)也是空的
          注:為什么叫鉤子,子類(lèi)可以通過(guò)這個(gè)鉤子(方法),控制父類(lèi),因?yàn)檫@個(gè)鉤子實(shí)際是父類(lèi)的方法(空方法)!

          Spring模板方法模式實(shí)質(zhì):

          是模板方法模式和回調(diào)模式的結(jié)合,是Template Method不需要繼承的另一種實(shí)現(xiàn)方式。Spring幾乎所有的外接擴(kuò)展都采用這種模式。

          具體實(shí)現(xiàn):

          JDBC的抽象和對(duì)Hibernate的集成,都采用了一種理念或者處理方式,那就是模板方法模式與相應(yīng)的Callback接口相結(jié)合。
          采用模板方法模式是為了以一種統(tǒng)一而集中的方式來(lái)處理資源的獲取和釋放,以JdbcTempalte為例:

          public?abstract?class?JdbcTemplate?{
          ?????public?final?Object?execute(String?sql){
          ????????Connection?con=null;
          ????????Statement?stmt=null;
          ????????try{
          ????????????con=getConnection();
          ????????????stmt=con.createStatement();
          ????????????Object?retValue=executeWithStatement(stmt,sql);
          ????????????return?retValue;
          ????????}catch(SQLException?e){
          ?????????????...
          ????????}finally{
          ????????????closeStatement(stmt);
          ????????????releaseConnection(con);
          ????????}
          ????}
          ????protected?abstract?Object?executeWithStatement(Statement???stmt,?String?sql);
          }

          引入回調(diào)原因:

          JdbcTemplate是抽象類(lèi),不能夠獨(dú)立使用,我們每次進(jìn)行數(shù)據(jù)訪(fǎng)問(wèn)的時(shí)候都要給出一個(gè)相應(yīng)的子類(lèi)實(shí)現(xiàn),這樣肯定不方便,所以就引入了回調(diào)。
          回調(diào)代碼

          public?interface?StatementCallback{
          ????Object?doWithStatement(Statement?stmt);
          }

          利用回調(diào)方法重寫(xiě)JdbcTemplate方法

          public?class?JdbcTemplate?{
          ????public?final?Object?execute(StatementCallback?callback){
          ????????Connection?con=null;
          ????????Statement?stmt=null;
          ????????try{
          ????????????con=getConnection();
          ????????????stmt=con.createStatement();
          ????????????Object?retValue=callback.doWithStatement(stmt);
          ????????????return?retValue;
          ????????}catch(SQLException?e){
          ????????????...
          ????????}finally{
          ????????????closeStatement(stmt);
          ????????????releaseConnection(con);
          ????????}
          ????}

          ????...//其它方法定義
          }

          Jdbc使用方法如下:

          JdbcTemplate?jdbcTemplate=...;
          ????final?String?sql=...;
          ????StatementCallback?callback=new?StatementCallback(){
          ????public?Object=doWithStatement(Statement?stmt){
          ????????return?...;
          ????}
          }
          jdbcTemplate.execute(callback);

          為什么JdbcTemplate沒(méi)有使用繼承?

          因?yàn)檫@個(gè)類(lèi)的方法太多,但是我們還是想用到JdbcTemplate已有的穩(wěn)定的、公用的數(shù)據(jù)庫(kù)連接,那么我們?cè)趺崔k呢?
          我們可以把變化的東西抽出來(lái)作為一個(gè)參數(shù)傳入JdbcTemplate的方法中。但是變化的東西是一段代碼,而且這段代碼會(huì)用到JdbcTemplate中的變量。怎么辦?
          那我們就用回調(diào)對(duì)象吧。在這個(gè)回調(diào)對(duì)象中定義一個(gè)操縱JdbcTemplate中變量的方法,我們?nèi)?shí)現(xiàn)這個(gè)方法,就把變化的東西集中到這里了。然后我們?cè)賯魅脒@個(gè)回調(diào)對(duì)象到JdbcTemplate,從而完成了調(diào)用。

          推薦閱讀:

          網(wǎng)曝字節(jié)跳動(dòng)將實(shí)行“1075”工作制!網(wǎng)友:這不是眾所周知的嘛!守則的有多少?JAVA8之妙用Optional解決判斷Null為空問(wèn)題

          最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)個(gè)「在看」,點(diǎn)擊上方小卡片,進(jìn)入公眾號(hào)后回復(fù)「面試題」領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          朕已閱?

          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)

          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一级 片内射视频播放蘑菇 | 成人做爰A片一区二区app | 麻豆国产精品一区 | 日一日射一射 | 依人大香蕉在线 |