驚呆了,spring中竟然有12種定義bean的方法(spring定義bean的方式)

      網(wǎng)友投稿 1254 2025-04-01

      前言

      在龐大的java體系中,spring有著舉足輕重的地位,它給每位開發(fā)者帶來了極大的便利和驚喜。我們都知道spring是創(chuàng)建和管理bean的工廠,它提供了多種定義bean的方式,能夠滿足我們?nèi)粘9ぷ髦械亩喾N業(yè)務(wù)場景。

      那么問題來了,你知道spring中有哪些方式可以定義bean?

      我估計很多人會說出以下三種:

      沒錯,但我想說的是以上三種方式只是開胃小菜,實際上spring的功能遠比你想象中更強大。

      各位看官如果不信,請繼續(xù)往下看。

      1. xml文件配置bean

      我們先從xml配置bean開始,它是spring最早支持的方式。后來,隨著springboot越來越受歡迎,該方法目前已經(jīng)用得很少了,但我建議我們還是有必要了解一下。

      1.1 構(gòu)造器

      如果你之前有在bean.xml文件中配置過bean的經(jīng)歷,那么對如下的配置肯定不會陌生:

      這種方式是以前使用最多的方式,它默認使用了無參構(gòu)造器創(chuàng)建bean。

      當然我們還可以使用有參的構(gòu)造器,通過標簽來完成配置。

      其中:

      index表示下標,從0開始。

      value表示常量值

      ref表示引用另一個bean

      1.2 setter方法

      除此之外,spring還提供了另外一種思路:通過setter方法設(shè)置bean所需參數(shù),這種方式耦合性相對較低,比有參構(gòu)造器使用更為廣泛。

      先定義Person實體:

      @Data

      public?class?Person?{

      private?String?name;

      private?int?age;

      }

      它里面包含:成員變量name和age,getter/setter方法。

      然后在bean.xml文件中配置bean時,加上標簽設(shè)置bean所需參數(shù)。

      1.3 靜態(tài)工廠

      這種方式的關(guān)鍵是需要定義一個工廠類,它里面包含一個創(chuàng)建bean的靜態(tài)方法。例如:

      public?class?SusanBeanFactory?{

      public?static?Person?createPerson(String?name,?int?age)?{

      return?new?Person(name,?age);

      }

      }

      接下來定義Person類如下:

      @AllArgsConstructor

      @NoArgsConstructor

      @Data

      public?class?Person?{

      private?String?name;

      private?int?age;

      }

      它里面包含:成員變量name和age,getter/setter方法,無參構(gòu)造器和全參構(gòu)造器。

      然后在bean.xml文件中配置bean時,通過factory-method參數(shù)指定靜態(tài)工廠方法,同時通過設(shè)置相關(guān)參數(shù)。

      1.4 實例工廠方法

      這種方式也需要定義一個工廠類,但里面包含非靜態(tài)的創(chuàng)建bean的方法。

      public?class?SusanBeanFactory?{

      public?Person?createPerson(String?name,?int?age)?{

      return?new?Person(name,?age);

      }

      }

      Person類跟上面一樣,就不多說了。

      然后bean.xml文件中配置bean時,需要先配置工廠bean。然后在配置實例bean時,通過factory-bean參數(shù)指定該工廠bean的引用。

      1.5 FactoryBean

      不知道大家有沒有發(fā)現(xiàn),上面的實例工廠方法每次都需要創(chuàng)建一個工廠類,不方面統(tǒng)一管理。

      這時我們可以使用FactoryBean接口。

      public?class?UserFactoryBean?implements?FactoryBean?{

      @Override

      public?User?getObject()?throws?Exception?{

      return?new?User();

      }

      @Override

      public?Class?getObjectType()?{

      return?User.class;

      }

      }

      在它的getObject方法中可以實現(xiàn)我們自己的邏輯創(chuàng)建對象,并且在getObjectType方法中我們可以定義對象的類型。

      然后在bean.xml文件中配置bean時,只需像普通的bean一樣配置即可。

      輕松搞定,so easy。

      注意:getBean("userFactoryBean");獲取的是getObject方法中返回的對象。而getBean("&userFactoryBean");獲取的才是真正的UserFactoryBean對象。

      我們通過上面五種方式,在bean.xml文件中把bean配置好之后,spring就會自動掃描和解析相應(yīng)的標簽,并且?guī)臀覀儎?chuàng)建和實例化bean,然后放入spring容器中。

      雖說基于xml文件的方式配置bean,簡單而且非常靈活,比較適合一些小項目。但如果遇到比較復(fù)雜的項目,則需要配置大量的bean,而且bean之間的關(guān)系錯綜復(fù)雜,這樣久而久之會導(dǎo)致xml文件迅速膨脹,非常不利于bean的管理。

      2. Component注解

      為了解決bean太多時,xml文件過大,從而導(dǎo)致膨脹不好維護的問題。在spring2.5中開始支持:@Component、@Repository、@Service、@Controller等注解定義bean。

      如果你有看過這些注解的源碼的話,就會驚奇得發(fā)現(xiàn):其實后三種注解也是@Component。

      @Component系列注解的出現(xiàn),給我們帶來了極大的便利。我們不需要像以前那樣在bean.xml文件中配置bean了,現(xiàn)在只用在類上加Component、Repository、Service、Controller,這四種注解中的任意一種,就能輕松完成bean的定義。

      @Service

      public?class?PersonService?{

      public?String?get()?{

      return?"data";

      }

      }

      其實,這四種注解在功能上沒有特別的區(qū)別,不過在業(yè)界有個不成文的約定:

      Controller 一般用在控制層

      Service 一般用在業(yè)務(wù)層

      Repository 一般用在數(shù)據(jù)層

      Component 一般用在公共組件上

      太棒了,簡直一下子解放了我們的雙手。

      不過,需要特別注意的是,通過這種@Component掃描注解的方式定義bean的前提是:需要先配置掃描路徑。

      目前常用的配置掃描路徑的方式如下:

      在applicationContext.xml文件中使用標簽。例如:

      在springboot的啟動類上加上@ComponentScan注解,例如:

      @ComponentScan(basePackages?=?"com.sue.cache")

      @SpringBootApplication

      public?class?Application?{

      public?static?void?main(String[]?args)?{

      new?SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);

      }

      }

      直接在SpringBootApplication注解上加,它支持ComponentScan功能:

      @SpringBootApplication(scanBasePackages?=?"com.sue.cache")

      public?class?Application?{

      public?static?void?main(String[]?args)?{

      new?SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);

      }

      }

      當然,如果你需要掃描的類跟springboot的入口類,在同一級或者子級的包下面,無需指定scanBasePackages參數(shù),spring默認會從入口類的同一級或者子級的包去找。

      @SpringBootApplication

      public?class?Application?{

      public?static?void?main(String[]?args)?{

      new?SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);

      }

      }

      此外,除了上述四種@Component注解之外,springboot還增加了@RestController注解,它是一種特殊的@Controller注解,所以也是@Component注解。

      @RestController還支持@ResponseBody注解的功能,即將接口響應(yīng)數(shù)據(jù)的格式自動轉(zhuǎn)換成json。

      @Component系列注解已經(jīng)讓我們愛不釋手了,它目前是我們?nèi)粘9ぷ髦凶疃嗟亩xbean的方式。

      3. JavaConfig

      @Component系列注解雖說使用起來非常方便,但是bean的創(chuàng)建過程完全交給spring容器來完成,我們沒辦法自己控制。

      spring從3.0以后,開始支持JavaConfig的方式定義bean。它可以看做spring的配置文件,但并非真正的配置文件,我們需要通過編碼java代碼的方式創(chuàng)建bean。例如:

      @Configuration

      public?class?MyConfiguration?{

      @Bean

      public?Person?person()?{

      return?new?Person();

      }

      }

      在JavaConfig類上加@Configuration注解,相當于配置了標簽。而在方法上加@Bean注解,相當于配置了標簽。

      此外,springboot還引入了一些列的@Conditional注解,用來控制bean的創(chuàng)建。

      @Configuration

      public?class?MyConfiguration?{

      @ConditionalOnClass(Country.class)

      @Bean

      public?Person?person()?{

      return?new?Person();

      }

      }

      @ConditionalOnClass注解的功能是當項目中存在Country類時,才實例化Person類。換句話說就是,如果項目中不存在Country類,就不實例化Person類。

      這個功能非常有用,相當于一個開關(guān)控制著Person類,只有滿足一定條件才能實例化。

      spring中使用比較多的Conditional還有:

      ConditionalOnBean

      ConditionalOnProperty

      ConditionalOnMissingClass

      ConditionalOnMissingBean

      驚呆了,spring中竟然有12種定義bean的方法(spring定義bean的方式)

      ConditionalOnWebApplication

      如果你對這些功能比較感興趣,可以看看《spring中那些讓你愛不釋手的代碼技巧(續(xù)集)》,這是我之前寫的一篇文章,里面做了更詳細的介紹。

      下面用一張圖整體認識一下@Conditional家族:

      nice,有了這些功能,我們終于可以告別麻煩的xml時代了。

      4. Import注解

      通過前面介紹的@Configuration和@Bean相結(jié)合的方式,我們可以通過代碼定義bean。但這種方式有一定的局限性,它只能創(chuàng)建該類中定義的bean實例,不能創(chuàng)建其他類的bean實例,如果我們想創(chuàng)建其他類的bean實例該怎么辦呢?

      這時可以使用@Import注解導(dǎo)入。

      4.1 普通類

      spring4.2之后@Import注解可以實例化普通類的bean實例。例如:

      先定義了Role類:

      @Data

      public?class?Role?{

      private?Long?id;

      private?String?name;

      }

      接下來使用@Import注解導(dǎo)入Role類:

      @Import(Role.class)

      @Configuration

      public?class?MyConfig?{

      }

      然后在調(diào)用的地方通過@Autowired注解注入所需的bean。

      @RequestMapping("/")

      @RestController

      public?class?TestController?{

      @Autowired

      private?Role?role;

      @GetMapping("/test")

      public?String?test()?{

      System.out.println(role);

      return?"test";

      }

      }

      聰明的你可能會發(fā)現(xiàn),我沒有在任何地方定義過Role的bean,但spring卻能自動創(chuàng)建該類的bean實例,這是為什么呢?

      這也許正是@Import注解的強大之處。

      此時,有些朋友可能會問:@Import注解能定義單個類的bean,但如果有多個類需要定義bean該怎么辦呢?

      恭喜你,這是個好問題,因為@Import注解也支持。

      @Import({Role.class,?User.class})

      @Configuration

      public?class?MyConfig?{

      }

      甚至,如果你想偷懶,不想寫這種MyConfig類,springboot也歡迎。

      @Import({Role.class,?User.class})

      @SpringBootApplication(exclude?=?{DataSourceAutoConfiguration.class,

      DataSourceTransactionManagerAutoConfiguration.class})

      public?class?Application?{

      public?static?void?main(String[]?args)?{

      new?SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);

      }

      }

      可以將@Import加到springboot的啟動類上。

      這樣也能生效?

      springboot的啟動類一般都會加@SpringBootApplication注解,該注解上加了@SpringBootConfiguration注解。

      而@SpringBootConfiguration注解,上面又加了@Configuration注解所以,springboot啟動類本身帶有@Configuration注解的功能。

      意不意外?驚不驚喜?

      4.2 Configuration類

      上面介紹了@Import注解導(dǎo)入普通類的方法,它同時也支持導(dǎo)入Configuration類。

      先定義一個Configuration類:

      @Configuration

      public?class?MyConfig2?{

      @Bean

      public?User?user()?{

      return??new?User();

      }

      @Bean

      public?Role?role()?{

      return?new?Role();

      }

      }

      然后在另外一個Configuration類中引入前面的Configuration類:

      @Import({MyConfig2.class})

      @Configuration

      public?class?MyConfig?{

      }

      這種方式,如果MyConfig2類已經(jīng)在spring指定的掃描目錄或者子目錄下,則MyConfig類會顯得有點多余。因為MyConfig2類本身就是一個配置類,它里面就能定義bean。

      但如果MyConfig2類不在指定的spring掃描目錄或者子目錄下,則通過MyConfig類的導(dǎo)入功能,也能把MyConfig2類識別成配置類。這就有點厲害了喔。

      其實下面還有更高端的玩法。

      swagger作為一個優(yōu)秀的文檔生成框架,在spring項目中越來越受歡迎。接下來,我們以swagger2為例,介紹一下它是如何導(dǎo)入相關(guān)類的。

      眾所周知,我們引入swagger相關(guān)jar包之后,只需要在springboot的啟動類上加上@EnableSwagger2注解,就能開啟swagger的功能。

      其中@EnableSwagger2注解中導(dǎo)入了Swagger2DocumentationConfiguration類。

      該類是一個Configuration類,它又導(dǎo)入了另外兩個類:

      SpringfoxWebMvcConfiguration

      SwaggerCommonConfiguration

      SpringfoxWebMvcConfiguration類又會導(dǎo)入新的Configuration類,并且通過@ComponentScan注解掃描了一些其他的路徑。

      SwaggerCommonConfiguration同樣也通過@ComponentScan注解掃描了一些額外的路徑。

      如此一來,我們通過一個簡單的@EnableSwagger2注解,就能輕松的導(dǎo)入swagger所需的一系列bean,并且擁有swagger的功能。

      還有什么好說的,狂起,簡直完美。

      4.3 ImportSelector

      上面提到的Configuration類,它的功能非常強大。但怎么說呢,它不太適合加復(fù)雜的判斷條件,根據(jù)某些條件定義這些bean,根據(jù)另外的條件定義那些bean。

      那么,這種需求該怎么實現(xiàn)呢?

      這時就可以使用ImportSelector接口了。

      首先定義一個類實現(xiàn)ImportSelector接口:

      public?class?DataImportSelector?implements?ImportSelector?{

      @Override

      public?String[]?selectImports(AnnotationMetadata?importingClassMetadata)?{

      return?new?String[]{"com.sue.async.service.User",?"com.sue.async.service.Role"};

      }

      }

      重寫selectImports方法,在該方法中指定需要定義bean的類名,注意要包含完整路徑,而非相對路徑。

      然后在MyConfig類上@Import導(dǎo)入這個類即可:

      @Import({DataImportSelector.class})

      @Configuration

      public?class?MyConfig?{

      }

      朋友們是不是又發(fā)現(xiàn)了一個新大陸?

      不過,這個注解還有更牛逼的用途。

      @EnableAutoConfiguration注解中導(dǎo)入了AutoConfigurationImportSelector類,并且里面包含系統(tǒng)參數(shù)名稱:spring.boot.enableautoconfiguration。AutoConfigurationImportSelector類實現(xiàn)了ImportSelector接口。

      并且重寫了selectImports方法,該方法會根據(jù)某些注解去找所有需要創(chuàng)建bean的類名,然后返回這些類名。其中在查找這些類名之前,先調(diào)用isEnabled方法,判斷是否需要繼續(xù)查找。該方法會根據(jù)ENABLED_OVERRIDE_PROPERTY的值來作為判斷條件。而這個值就是spring.boot.enableautoconfiguration。

      換句話說,這里能根據(jù)系統(tǒng)參數(shù)控制bean是否需要被實例化,優(yōu)秀。

      我個人認為實現(xiàn)ImportSelector接口的好處主要有以下兩點:

      把某個功能的相關(guān)類,可以放到一起,方面管理和維護。

      重寫selectImports方法時,能夠根據(jù)條件判斷某些類是否需要被實例化,或者某個條件實例化這些bean,其他的條件實例化那些bean等。我們能夠非常靈活的定制化bean的實例化。

      4.4 ImportBeanDefinitionRegistrar

      我們通過上面的這種方式,確實能夠非常靈活的自定義bean。

      但它的自定義能力,還是有限的,它沒法自定義bean的名稱和作用域等屬性。

      有需求,就有解決方案。

      接下來,我們一起看看ImportBeanDefinitionRegistrar接口的神奇之處。

      先定義CustomImportSelector類實現(xiàn)ImportBeanDefinitionRegistrar接口:

      public?class?CustomImportSelector?implements?ImportBeanDefinitionRegistrar?{

      @Override

      public?void?registerBeanDefinitions(AnnotationMetadata?importingClassMetadata,?BeanDefinitionRegistry?registry)?{

      RootBeanDefinition?roleBeanDefinition?=?new?RootBeanDefinition(Role.class);

      registry.registerBeanDefinition("role",?roleBeanDefinition);

      RootBeanDefinition?userBeanDefinition?=?new?RootBeanDefinition(User.class);

      userBeanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);

      registry.registerBeanDefinition("user",?userBeanDefinition);

      }

      }

      重寫registerBeanDefinitions方法,在該方法中我們可以獲取BeanDefinitionRegistry對象,通過它去注冊bean。不過在注冊bean之前,我們先要創(chuàng)建BeanDefinition對象,它里面可以自定義bean的名稱、作用域等很多參數(shù)。

      然后在MyConfig類上導(dǎo)入上面的類:

      @Import({CustomImportSelector.class})

      @Configuration

      public?class?MyConfig?{

      }

      我們所熟悉的fegin功能,就是使用ImportBeanDefinitionRegistrar接口實現(xiàn)的:具體細節(jié)就不多說了,有興趣的朋友可以加我微信找我私聊。

      5. PostProcessor

      除此之外,spring還提供了專門注冊bean的接口:BeanDefinitionRegistryPostProcessor。

      該接口的方法postProcessBeanDefinitionRegistry上有這樣一段描述:修改應(yīng)用程序上下文的內(nèi)部bean定義注冊表標準初始化。所有常規(guī)bean定義都將被加載,但是還沒有bean被實例化。這允許進一步添加在下一個后處理階段開始之前定義bean。

      如果用這個接口來定義bean,我們要做的事情就變得非常簡單了。只需定義一個類實現(xiàn)BeanDefinitionRegistryPostProcessor接口。

      @Component

      public?class?MyRegistryPostProcessor?implements?BeanDefinitionRegistryPostProcessor?{

      @Override

      public?void?postProcessBeanDefinitionRegistry(BeanDefinitionRegistry?registry)?throws?BeansException?{

      RootBeanDefinition?roleBeanDefinition?=?new?RootBeanDefinition(Role.class);

      registry.registerBeanDefinition("role",?roleBeanDefinition);

      RootBeanDefinition?userBeanDefinition?=?new?RootBeanDefinition(User.class);

      userBeanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);

      registry.registerBeanDefinition("user",?userBeanDefinition);

      }

      @Override

      public?void?postProcessBeanFactory(ConfigurableListableBeanFactory?beanFactory)?throws?BeansException?{

      }

      }

      重寫postProcessBeanDefinitionRegistry方法,在該方法中能夠獲取BeanDefinitionRegistry對象,它負責(zé)bean的注冊工作。

      不過細心的朋友可能會發(fā)現(xiàn),里面還多了一個postProcessBeanFactory方法,沒有做任何實現(xiàn)。

      這個方法其實是它的父接口:BeanFactoryPostProcessor里的方法。

      在應(yīng)用程序上下文的標準bean工廠之后修改其內(nèi)部bean工廠初始化。所有bean定義都已加載,但沒有bean將被實例化。這允許重寫或添加屬性甚至可以初始化bean。

      @Component

      public?class?MyPostProcessor?implements?BeanFactoryPostProcessor?{

      @Override

      public?void?postProcessBeanFactory(ConfigurableListableBeanFactory?beanFactory)?throws?BeansException?{

      DefaultListableBeanFactory?registry?=?(DefaultListableBeanFactory)beanFactory;

      RootBeanDefinition?roleBeanDefinition?=?new?RootBeanDefinition(Role.class);

      registry.registerBeanDefinition("role",?roleBeanDefinition);

      RootBeanDefinition?userBeanDefinition?=?new?RootBeanDefinition(User.class);

      userBeanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);

      registry.registerBeanDefinition("user",?userBeanDefinition);

      }

      }

      既然這兩個接口都能注冊bean,那么他們有什么區(qū)別?

      BeanDefinitionRegistryPostProcessor 更側(cè)重于bean的注冊

      BeanFactoryPostProcessor 更側(cè)重于對已經(jīng)注冊的bean的屬性進行修改,雖然也可以注冊bean。

      此時,有些朋友可能會問:既然拿到BeanDefinitionRegistry對象就能注冊bean,那通過BeanFactoryAware的方式是不是也能注冊bean呢?

      從下面這張圖能夠看出DefaultListableBeanFactory就實現(xiàn)了BeanDefinitionRegistry接口。

      這樣一來,我們?nèi)绻軌颢@取DefaultListableBeanFactory對象的實例,然后調(diào)用它的注冊方法,不就可以注冊bean了?

      說時遲那時快,定義一個類實現(xiàn)BeanFactoryAware接口:

      @Component

      public?class?BeanFactoryRegistry?implements?BeanFactoryAware?{

      @Override

      public?void?setBeanFactory(BeanFactory?beanFactory)?throws?BeansException?{

      DefaultListableBeanFactory?registry?=?(DefaultListableBeanFactory)?beanFactory;

      RootBeanDefinition?rootBeanDefinition?=?new?RootBeanDefinition(User.class);

      registry.registerBeanDefinition("user",?rootBeanDefinition);

      RootBeanDefinition?userBeanDefinition?=?new?RootBeanDefinition(User.class);

      userBeanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);

      registry.registerBeanDefinition("user",?userBeanDefinition);

      }

      }

      重寫setBeanFactory方法,在該方法中能夠獲取BeanFactory對象,它能夠強制轉(zhuǎn)換成DefaultListableBeanFactory對象,然后通過該對象的實例注冊bean。

      當你滿懷喜悅的運行項目時,發(fā)現(xiàn)竟然報錯了:

      為什么會報錯?

      spring中bean的創(chuàng)建過程順序大致如下:BeanFactoryAware接口是在bean創(chuàng)建成功,并且完成依賴注入之后,在真正初始化之前才被調(diào)用的。在這個時候去注冊bean意義不大,因為這個接口是給我們獲取bean的,并不建議去注冊bean,會引發(fā)很多問題。

      此外,ApplicationContextRegistry和ApplicationListener接口也有類似的問題,我們可以用他們獲取bean,但不建議用它們注冊bean。

      Keycloak簡單幾步實現(xiàn)對Spring Boot應(yīng)用的權(quán)限控制

      2021-07-09

      OAuth 2.0只是授權(quán)協(xié)議,OIDC才是認證授權(quán)協(xié)議

      2021-07-12

      Spring XML

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:關(guān)于云存儲效率的思考
      下一篇:滾雪球學(xué) Python】2. 無門檻學(xué)會數(shù)據(jù)類型與輸入、輸出函數(shù),(滾雪球理論)
      相關(guān)文章
      亚洲国产精品无码久久久久久曰| 偷自拍亚洲视频在线观看99| 亚洲毛片在线免费观看| 亚洲一级毛片中文字幕| 亚洲youwu永久无码精品| 国产亚洲综合网曝门系列| 亚洲AV无码国产精品色| 亚洲高清有码中文字| 自怕偷自怕亚洲精品| 亚洲AV无码久久寂寞少妇| 亚洲中文字幕无码久久2017| 亚洲精品国精品久久99热| 国产亚洲精品仙踪林在线播放| 久久亚洲国产成人影院| 亚洲精品免费在线| 亚洲美女视频免费| 亚洲成av人片在线看片| 亚洲无人区视频大全| 亚洲日本视频在线观看| 亚洲天堂男人天堂| 国产日产亚洲系列最新| 久久精品亚洲男人的天堂| 亚洲中文字幕久久精品无码APP| 亚洲一区二区三区在线观看精品中文| 国产精品亚洲视频| 好看的电影网站亚洲一区| 亚洲av福利无码无一区二区| 亚洲国产精品自在线一区二区| 亚洲AV无码成人专区片在线观看 | 亚洲日韩一区二区三区| 国产精品亚洲精品| 亚洲国产成人综合精品| 国产亚洲成在线播放va| 亚洲精品一级无码鲁丝片| a级亚洲片精品久久久久久久| 亚洲精品乱码久久久久66| 国产亚洲免费的视频看| 亚洲人成网www| 内射少妇36P亚洲区| 亚洲国产午夜精品理论片| 亚洲中文字幕一二三四区|