久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springboot教程(一)

發(fā)布時(shí)間:2024/9/16 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot教程(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

擼了今年阿里、頭條和美團(tuán)的面試,我有一個(gè)重要發(fā)現(xiàn).......>>>

使用jdk:1.8、maven:3.3.3

spring獲取Bean的方式

pom.xml文件內(nèi)容:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.ac.iie</groupId><artifactId>spring-course</artifactId><version>1.0-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.0.RELEASE</version></dependency></dependencies> </project>

配置類MyConfig.java:

package com.edu.spring;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;/*** 配置類*/@Configuration public class MyConfig {// 配置一個(gè)bean@Beanpublic MyBean createMyBean(){return new MyBean();}}

MyBean.java

package com.edu.spring;public class MyBean { }

主函數(shù):App.java

package com.edu.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);// 從容器中獲取bean---從類型獲取System.out.println(context.getBean(MyBean.class));// 從容器中獲取bean---從名字獲取,默認(rèn)名字是方法名System.out.println(context.getBean("createMyBean"));context.close();} }

輸出結(jié)果如下:

com.edu.spring.MyBean@1445d7f
com.edu.spring.MyBean@1445d7f

如果需要指定bean名字,需要修改MyConfig.java:

@Configuration public class MyConfig {// 配置一個(gè)bean@Bean(name = "myBean")public MyBean createMyBean(){return new MyBean();}}

然后在App.java指定Bean的名字:這樣就無法根據(jù)方法名獲取Bean了

public class App {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);// 從容器中獲取bean---從類型獲取System.out.println(context.getBean(MyBean.class));// 從容器中獲取bean---從名字獲取,默認(rèn)名字是方法名// System.out.println(context.getBean("createMyBean"));// 從容器中獲取bean---從指定名字獲取System.out.println(context.getBean("myBean"));context.close();} }

Bean默認(rèn)是單例

我們可以看到,Bean是單例的,兩次打印出的對(duì)象是一樣的。

如果我們想修改Bean的單例為多例,修改MyConfig.java如下(添加scope(prototype)):

@Configuration public class MyConfig {// 配置一個(gè)bean@Bean(name = "myBean")@Scope("prototype")public MyBean createMyBean(){return new MyBean();}}

打印如下:

com.edu.spring.MyBean@10b48321
com.edu.spring.MyBean@6b67034

FactoryBean

新建方法JeepFactoryBean.java

package com.edu.spring;import org.springframework.beans.factory.FactoryBean;public class JeepFactoryBean implements FactoryBean<Jeep> {/*** 創(chuàng)建的實(shí)例對(duì)象* @return* @throws Exception*/@Overridepublic Jeep getObject() throws Exception {return new Jeep();}/**** @return*/@Overridepublic Class<?> getObjectType() {return Jeep.class;}@Overridepublic boolean isSingleton() {return true;} }

在MyConfig.java中添加配置:

@Beanpublic JeepFactoryBean createJeepFactoryBean(){return new JeepFactoryBean();}

可以在App.java中得到Jeep.class。

System.out.println(context.getBean(Jeep.class)); System.out.println(context.getBean("createJeepFactoryBean"));

如果要獲取JeepFactoryBean本身,而不是工廠生產(chǎn)出的類,可以通過下面的兩種方式獲取:

System.out.println(context.getBean(JeepFactoryBean.class)); System.out.println(context.getBean("&createJeepFactoryBean"));

目前有兩種方式進(jìn)行Bean的裝配,一種是使用FactoryBean,一種是原始方式

使用第三種裝配

新建CarFactory.java

public class CarFactory {public Car create(){return new Car();} }

新建Car.java

配置MyConfig.java

@Beanpublic Car createJeep(CarFactory carFactory){return carFactory.create();}@Beanpublic CarFactory createCarFactory(){return new CarFactory();}

獲取對(duì)象:

System.out.println(context.getBean(Car.class));

因?yàn)?#xff0c;在Bean的裝配過程中,需要參數(shù)的時(shí)候,spring會(huì)默認(rèn)從當(dāng)前容器中獲取到對(duì)應(yīng)的參數(shù),然后注入。

Bean初始化,在Bean初始化時(shí),進(jìn)行一些操作。

方式一:

創(chuàng)建Cat.java

package com.edu.spring;import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean;public class Cat implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("====afterPropertiesSet====");}@Overridepublic void destroy() throws Exception {System.out.println("====destroy====");} }

配置MyConfig.java

@Beanpublic Cat createCat(){return new Cat();}

獲得cat

System.out.println(context.getBean(Cat.class));

控制臺(tái)打印:

====afterPropertiesSet==== com.edu.spring.MyBean@7fe8ea47 com.edu.spring.MyBean@226a82c4 com.edu.spring.JeepFactoryBean@731f8236 com.edu.spring.JeepFactoryBean@731f8236 com.edu.spring.Jeep@255b53dc com.edu.spring.Jeep@255b53dc com.edu.spring.Car@1dd92fe2 com.edu.spring.Cat@6b53e23f ====destroy====

方法二:

創(chuàng)建Dog.java

package com.edu.spring;public class Dog {public void myInit(){System.out.println("init=====");}public void myDestory(){System.out.println("destory===");}}

在配置MyConfig.java時(shí)指定初始化時(shí)執(zhí)行和銷毀時(shí)執(zhí)行的方法

@Bean(initMethod = "myInit", destroyMethod = "myDestory")public Dog createDog(){return new Dog();}

方式三:

新建Fish.java

package com.edu.spring;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;public class Fish {@PostConstructpublic void initial(){System.out.println("fish init");}@PreDestroypublic void close(){System.out.println("fish close");}}

配置MyConfig.java

@Beanpublic Fish createFish(){return new Fish();}

Bean裝配

新建User.java

package com.edu.spring;import org.springframework.stereotype.Component;@Component public class User { }

修改App.java,將User.class添加到容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class, User.class); System.out.println(context.getBean(User.class));

但是使用@Component,則無法使用@Bean(initMethod = "myInit", destroyMethod = "myDestory")設(shè)置初始化和銷毀的方法

此外,默認(rèn)的名字是類名。可以指定名字:

@Component("myUser")

如果此時(shí)同樣在MyConfig.java中,配置一個(gè)Bean,

@Beanpublic User createUser(){return new User();}

則會(huì)報(bào)錯(cuò):

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.edu.spring.User' available: expected single matching bean but found 2: myUser,createUserat org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1034)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)at com.edu.spring.App.main(App.java:24)

也就是說通過類型獲取User時(shí)找到了兩個(gè) 一個(gè)是myUser一個(gè)是createUser。如果我們通過名字來獲取就沒有問題了。

System.out.println(context.getBean("myUser"));

如果想獲取,User類型的所有對(duì)象,可以使用getBeansOfType方法。

除了使用Component,還可以使用Repository來裝配類,一般用在數(shù)據(jù)訪問層,而Component一般用于沒有明確角色的時(shí)候。

新建UserDao.java

@Repository public class UserDao { }

添加到AnnotationConfigApplicationContext中

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class, User.class, UserDao.class); System.out.println(context.getBean(UserDao.class));

還可以使用Service來裝配,一般用在業(yè)務(wù)邏輯層

新建UserService.java,

// 業(yè)務(wù)邏輯層 @Service public class UserService { }

添加到AnnotationConfigApplicationContext:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class, User.class, UserDao.class, UserService.class); System.out.println(context.getBean(UserService.class));

使用Controller來裝配,一般用于展示層,

package com.edu.spring;import org.springframework.stereotype.Controller;// 用在展示層 @Controller public class UserController { }

依賴注入

在User中,依賴UserService.java

User.java

package com.edu.spring;import org.springframework.stereotype.Component;@Component("myUser") public class User {private UserService userService;public UserService getUserService() {return userService;}public void setUserService(UserService userService) {this.userService = userService;}@Overridepublic String toString() {return "User{" +"userService=" + userService +'}';} }

在App.java中調(diào)用show方法

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class, User.class, UserDao.class, UserService.class, UserController.class); User user = context.getBean("myUser", User.class); user.show(); context.close();

輸出打印:

null

說明UserService沒有注入進(jìn)去,使用@AutoWired修飾UserService,便可以注入進(jìn)去了,同時(shí)也不需要set get方法了。

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;@Component("myUser") public class User {@Autowiredprivate UserService userService;@Overridepublic String toString() {return "UserService{" +"userDao=" + userDao +'}';}}

打印輸出:

User{userService=UserService{userDao=com.edu.spring.UserDao@3bbc39f8}}

說明成功注入進(jìn)去了。

如果繼續(xù)在MyConfig.java中裝配一個(gè)Bean:

@Beanpublic UserDao createUserDao(){return new UserDao();}

那么這時(shí),就會(huì)有兩個(gè)UserDao存在,就不知道用哪個(gè)對(duì)象,出現(xiàn)報(bào)錯(cuò):

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.edu.spring.UserDao' available: expected single matching bean but found 2: userDao,createUserDaoat org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1034)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)at com.edu.spring.App.main(App.java:26)

這時(shí)可以用兩個(gè)方法解決問題。

方法一:使用Qualifier注釋

@Service public class UserService {@Autowired@Qualifier("createUserDao")private UserDao userDao;@Overridepublic String toString() {return "UserService{" +"userDao=" + userDao +'}';} }

這樣就知道用哪一個(gè)對(duì)象了。(注意要將其他所有用到UserDao的地方,都需要使用Qualifier指明到底用哪一個(gè)userdao)

方法二:使用Primary注釋Bean

在MyConfig.java中:

@Bean@Primarypublic UserDao createUserDao(){return new UserDao();}

Primary用于有多個(gè)對(duì)象存在時(shí),首先尋找標(biāo)有Primary的對(duì)象,進(jìn)行注入。

如果要注入其他類,比如Car.java,需要使用Resource注釋來注入。

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;import javax.annotation.Resource;@Component("myUser") public class User {@Autowiredprivate UserService userService;// 使用JSR 250的注解@Resourceprivate Car car;@Overridepublic String toString() {return "User{" +"userService=" + userService +", car=" + car +'}';} }

輸出:User{userService=UserService{userDao=com.edu.spring.UserDao@1b083826}, car=com.edu.spring.Car@55a1c291}

說明Car.java 也注入進(jìn)來了。

此外還可以使用 JSR 330 的注解方式進(jìn)行注入,但是這種方式需要添加依賴:

<dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version></dependency>

嘗試將Cat.java注入進(jìn)去User。使用Inject注釋。

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;import javax.annotation.Resource; import javax.inject.Inject;@Component("myUser") public class User {// Spring提供的注解@Autowiredprivate UserService userService;// 使用JSR-250的注解@Resourceprivate Car car;// 使用JSR-330的注解@Injectprivate Cat cat;@Overridepublic String toString() {return "User{" +"userService=" + userService +", car=" + car +", cat=" + cat +'}';} }

控制臺(tái)顯示輸出:信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 說明JSR330 已經(jīng)起作用了。

User{userService=UserService{userDao=com.edu.spring.UserDao@55ca8de8}, car=com.edu.spring.Car@5d740a0f, cat=com.edu.spring.Cat@214b199c}
說明cat也成功注入進(jìn)去了。

我們發(fā)現(xiàn)AnnotationConfigApplicationContext很麻煩,每次都需要手動(dòng)去添加新的類。

我們可以使用包掃描的方式進(jìn)行類裝載,更加方便。

package com.edu.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AnnotationClient {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.edu.spring");System.out.println(context.getBean(Jeep.class));System.out.println(context.getBean("createJeepFactoryBean"));System.out.println(context.getBean(Car.class));System.out.println(context.getBean(Cat.class));System.out.println(context.getBean(Dog.class));System.out.println(context.getBean(Fish.class));System.out.println(context.getBean("myUser"));context.close();} }

如果我們想排除某一些類,這些類不想被掃描到。方法如下:

新建AnnotationScan.java

package com.edu.spring;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;@ComponentScan("com.edu.spring") @Configuration public class AnnotationScan { }

新建AnnotationClient2.java

package com.edu.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AnnotationClient2 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationScan.class);context.close();} }

這種方法同樣可以達(dá)到掃描包的效果。如果我們想排除Dog類,需要將MyConfig.java中的配置Dog的地方刪除,新建DogConfig.java

package com.edu.spring;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class DogConfig {@Bean(initMethod = "myInit", destroyMethod = "myDestory")public Dog createDog(){return new Dog();}}

修改AnnotationScan.java

package com.edu.spring;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType;@ComponentScan(basePackages = "com.edu.spring", excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = DogConfig.class)) @Configuration public class AnnotationScan { }

這樣就將Dog類排除了,然后執(zhí)行AnnotationClient2.java 就會(huì)報(bào)錯(cuò):

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.edu.spring.Dog' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:348)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)at com.edu.spring.AnnotationClient2.main(AnnotationClient2.java:13)

說明Dog已經(jīng)排除成功了。同樣可以排除UserController.java

因?yàn)閁serController上有注釋,可以直接排除。

package com.edu.spring;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType;@ComponentScan(basePackages = "com.edu.spring", excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {DogConfig.class, UserController.class})) @Configuration public class AnnotationScan { }

第二課

Spring有兩個(gè)核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他們都可代表Spring容器,Spring容器是生成Bean實(shí)例的工廠,并且管理容器中的Bean。

BeanFactory負(fù)責(zé)配置、創(chuàng)建、管理Bean,他有一個(gè)子接口:ApplicationContext,因此也稱之為Spring上下文。Spring容器負(fù)責(zé)管理Bean與Bean之間的依賴關(guān)系。

BeanFactory接口包含以下幾個(gè)基本方法:

  • Boolean containBean(String name):判斷Spring容器是否包含id為name的Bean實(shí)例。
  • <T> getBean(Class<T> requiredTypr):獲取Spring容器中屬于requiredType類型的唯一的Bean實(shí)例。
  • Object getBean(String name):返回Sprin容器中id為name的Bean實(shí)例。
  • <T> T getBean(String name,Class requiredType):返回容器中id為name,并且類型為requiredType的Bean
  • Class <?> getType(String name):返回容器中指定Bean實(shí)例的類型。?

?調(diào)用者只需使用getBean()方法即可獲得指定Bean的引用,無須關(guān)心Bean的實(shí)例化過程。即Bean實(shí)例的創(chuàng)建過程完全透明。

讓Bean獲取Spring容器

????在Spring中我們可以使用Spring容器中g(shù)etBean()方法來獲取Spring容器中的Bean實(shí)例。在這樣的訪問模式下,程序中總是持有Spring容器的引用。但是在實(shí)際的應(yīng)用中,Spring容器通常是采用聲明式方式配置產(chǎn)生:即開發(fā)者只要在web.xml文件中配置一個(gè)Listener,該Listener將會(huì)負(fù)責(zé)初始化Spring容器。在這種情況下,容器中Bean處于容器管理下,無須主動(dòng)訪問容器,只需要接受容器的注入管理即可。同時(shí)Bean實(shí)例的依賴關(guān)系通常也是由容器自動(dòng)注入,無須Bean實(shí)例主動(dòng)請(qǐng)求。

如何注入ApplicationContext?

新建myConfig.java

package com.edu.spring;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class MyConfig {@Beanpublic User createUser(){return new User();}}

新建User.java

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext;public class User {@Autowiredprivate ApplicationContext applicationContext;public void show(){System.out.println("user:" + applicationContext.getClass());}}

新建App.java

package com.edu.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.edu.spring");System.out.println(context.getBean(User.class));System.out.println(context.getBean("createUser"));context.getBean(User.class).show();context.close();} }

方法一:

在Use.java中使用AutoWired成功注入ApplicationContext。也可以使用JSR 250 和JSR330 方式注入

輸出如下:

com.edu.spring.User@6ee12bac com.edu.spring.User@6ee12bac user:class org.springframework.context.annotation.AnnotationConfigApplicationContext

方法二:

新建Book.java

package com.edu.spring;import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component;@Component public class Book implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void show(){System.out.println("book:" + applicationContext.getClass());}}

方法三:

新鍵Bank.java

package com.edu.spring;import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component;@Component public class Bank {private ApplicationContext applicationContext;public Bank (ApplicationContext applicationContext){this.applicationContext = applicationContext;}public void show(){System.out.println("bank:" + applicationContext.getClass());}}

這種方法同樣可以注入ApplicationContext。但是這個(gè)方法,構(gòu)造函數(shù)只能有一個(gè),如果有多個(gè)的話,就必須有一個(gè)無參的構(gòu)造函數(shù),此時(shí),spring會(huì)調(diào)用無參的構(gòu)造函數(shù)。構(gòu)造函數(shù)的參數(shù),必須都要在Spring容器中。

BeanPostProcessor

BeanPostProcessor會(huì)在每個(gè)bean初始化的時(shí)候,調(diào)用一次

新建EchoBeanPostProcessor.java

package com.edu.spring;import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component;/*** BeanPostProcessor會(huì)在每個(gè)bean初始化的時(shí)候,調(diào)用一次*/ @Component public class EchoBeanPostProcessor implements BeanPostProcessor {// 在bean依賴裝配(屬性設(shè)置完)完成之后觸發(fā)@Nullable@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("====postProcessBeforeInitialization======" + bean.getClass());return bean;}// 在bean init方法執(zhí)行之后觸發(fā)@Nullable@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("====postProcessAfterInitialization======" + bean.getClass());return bean;} }

打印輸出如下:

====postProcessBeforeInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessAfterInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessBeforeInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessAfterInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessBeforeInitialization======class com.edu.spring.Bank ====postProcessAfterInitialization======class com.edu.spring.Bank ====postProcessBeforeInitialization======class com.edu.spring.Book ====postProcessAfterInitialization======class com.edu.spring.Book ====postProcessBeforeInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$3a1c64d1 ====postProcessAfterInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$3a1c64d1 ====postProcessBeforeInitialization======class com.edu.spring.User ====postProcessAfterInitialization======class com.edu.spring.User com.edu.spring.User@482cd91f com.edu.spring.User@482cd91f user:class org.springframework.context.annotation.AnnotationConfigApplicationContext book:class org.springframework.context.annotation.AnnotationConfigApplicationContext bank:class org.springframework.context.annotation.AnnotationConfigApplicationContext

在每個(gè)bean初始化之前和之后執(zhí)行的方法。????

如果我們給User添加一個(gè)初始化方法init

user.java

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext;public class User {@Autowiredprivate ApplicationContext applicationContext;public void init(){System.out.println("user init");}public void show(){System.out.println("user:" + applicationContext.getClass());}}

在MyConfig.java中指定初始化方法:

package com.edu.spring;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class MyConfig {@Bean(initMethod = "init")public User createUser(){return new User();}}

則輸出結(jié)果如下:

====postProcessBeforeInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessAfterInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessBeforeInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessAfterInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessBeforeInitialization======class com.edu.spring.Bank ====postProcessAfterInitialization======class com.edu.spring.Bank ====postProcessBeforeInitialization======class com.edu.spring.Book ====postProcessAfterInitialization======class com.edu.spring.Book ====postProcessBeforeInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$3a1c64d1 ====postProcessAfterInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$3a1c64d1 ====postProcessBeforeInitialization======class com.edu.spring.User user init ====postProcessAfterInitialization======class com.edu.spring.User com.edu.spring.User@482cd91f com.edu.spring.User@482cd91f user:class org.springframework.context.annotation.AnnotationConfigApplicationContext book:class org.springframework.context.annotation.AnnotationConfigApplicationContext bank:class org.springframework.context.annotation.AnnotationConfigApplicationContext

說明postProcessBeforeInitialization方法是在bean init方法之前執(zhí)行,postProcessAfterInitialization方法是在bean init方法之后執(zhí)行。

修改User.java

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext;public class User {private ApplicationContext applicationContext;public void init(){System.out.println("user init");}public void show(){System.out.println("user:" + applicationContext.getClass());}@Autowiredpublic void setApplicationContext(ApplicationContext applicationContext) {System.out.println("applicationContext set");this.applicationContext = applicationContext;} }

Autowired既可以用在變量上,也可以用在方法上。

輸出結(jié)果如下:

====postProcessBeforeInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessAfterInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessBeforeInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessAfterInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessBeforeInitialization======class com.edu.spring.Bank ====postProcessAfterInitialization======class com.edu.spring.Bank ====postProcessBeforeInitialization======class com.edu.spring.Book ====postProcessAfterInitialization======class com.edu.spring.Book ====postProcessBeforeInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$50df4f2b ====postProcessAfterInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$50df4f2b applicationContext set ====postProcessBeforeInitialization======class com.edu.spring.User user init ====postProcessAfterInitialization======class com.edu.spring.User com.edu.spring.User@5b0abc94 com.edu.spring.User@5b0abc94 user:class org.springframework.context.annotation.AnnotationConfigApplicationContext book:class org.springframework.context.annotation.AnnotationConfigApplicationContext bank:class org.springframework.context.annotation.AnnotationConfigApplicationContext

說明依賴都裝配完成之后出發(fā)postProcessBeforeInitialization

代理對(duì)象

新建LogUser.java

package com.edu.spring;public class LogUser extends User {@Overridepublic void show() {System.out.println("log start ...");super.show();System.out.println("log end ...");} }

修改Use.java

public void show(){System.out.println("user:" + applicationContext);}

修改EchoBeanPostProcessor.java

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("====postProcessBeforeInitialization======" + bean.getClass());if(bean instanceof User){return new LogUser();}return bean;}

輸出結(jié)果如下:

====postProcessBeforeInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessAfterInitialization======class org.springframework.context.event.EventListenerMethodProcessor ====postProcessBeforeInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessAfterInitialization======class org.springframework.context.event.DefaultEventListenerFactory ====postProcessBeforeInitialization======class com.edu.spring.Bank ====postProcessAfterInitialization======class com.edu.spring.Bank ====postProcessBeforeInitialization======class com.edu.spring.Book ====postProcessAfterInitialization======class com.edu.spring.Book ====postProcessBeforeInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$50df4f2b ====postProcessAfterInitialization======class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$50df4f2b applicationContext set ====postProcessBeforeInitialization======class com.edu.spring.User user init ====postProcessAfterInitialization======class com.edu.spring.LogUser com.edu.spring.LogUser@75c072cb com.edu.spring.LogUser@75c072cb log start ... user:null log end ... book:class org.springframework.context.annotation.AnnotationConfigApplicationContext bank:class org.springframework.context.annotation.AnnotationConfigApplicationContext

可以對(duì)指定的Bean做一些處理,比如返回對(duì)象的代理對(duì)象。

spring擴(kuò)展二

目前我們知道BeanPostProcessor是在某個(gè)bean初始化的時(shí)候,進(jìn)行回調(diào)的,我們可以控制bean的初始化和其他的操作。如果我們想要對(duì)某個(gè)容器進(jìn)行初始化回調(diào),如何做?spring同樣留了接口, BeanFactoryPostProcessor,是在spring容器初始化之后進(jìn)行的

新建App.java

package com.edu.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.edu.spring");context.close();} }

新建MyBeanFactoryPostProcessor.java

package com.edu.spring;import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component;/*** BeanFactoryPostProcessor在spring容器的初始化之后出發(fā),而且只會(huì)觸發(fā)一次* 觸發(fā)的時(shí)機(jī)比BeanPostProcessor早*/ @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {System.out.println("============" + configurableListableBeanFactory.getBeanDefinitionCount());} }

運(yùn)行App.java 輸出結(jié)果如下:

============7

說明即使我們什么都不做,spring容器還是有很多個(gè)bean的。

新建User.java

public class User {public void init(){System.out.println("user init");} }

新建MyConfig.java

package com.edu.spring;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class MyConfig {@Bean(initMethod = "init")public User createUser(){return new User();}@Beanpublic User createUser2(){return new User();}}

運(yùn)行App.java,輸出結(jié)果如下:

============10 user init

新建MyBeanPostProcessor.java,對(duì)比BeanPostProcessor和BeanFactoryPostProcessor執(zhí)行順序是什么

package com.edu.spring;import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component;@Component public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("====postProcessBeforeInitialization=====" + bean.getClass());return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("====postProcessAfterInitialization=====" + bean.getClass());return bean;} }

運(yùn)行輸出結(jié)果:

============11 四月 22, 2019 3:47:16 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring ====postProcessBeforeInitialization=====class org.springframework.context.event.EventListenerMethodProcessor ====postProcessAfterInitialization=====class org.springframework.context.event.EventListenerMethodProcessor ====postProcessBeforeInitialization=====class org.springframework.context.event.DefaultEventListenerFactory ====postProcessAfterInitialization=====class org.springframework.context.event.DefaultEventListenerFactory ====postProcessBeforeInitialization=====class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$a601222d ====postProcessAfterInitialization=====class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$a601222d ====postProcessBeforeInitialization=====class com.edu.spring.User user init ====postProcessAfterInitialization=====class com.edu.spring.User ====postProcessBeforeInitialization=====class com.edu.spring.User ====postProcessAfterInitialization=====class com.edu.spring.User

說明BeanFactoryPostProcessor最先執(zhí)行,但只會(huì)執(zhí)行一次,因?yàn)槿萜鲌?zhí)行完成一次。

BeanDefinitionRegistry

我們使用Component注釋來注冊(cè)一個(gè)bean,但這是靜態(tài)的注冊(cè),我們可以通過BeanDefinitionRegistry來動(dòng)態(tài)注冊(cè)一個(gè)Bean。

新建一個(gè)要注入的類Person.java

package com.edu.spring;public class Person {private String name;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;} }

新建MyBeanDefinitionRegistryPostProcessor.java,注入十個(gè)Person類,并給他們的屬性賦值。

package com.edu.spring;import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.stereotype.Component;/*** BeanDefinitionRegistryPostProcessor可以拿到BeanDefinitionRegistry,ConfigurableListableBeanFactory兩個(gè)對(duì)象* BeanDefinitionRegistry可以動(dòng)態(tài)注入bean*/ @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {for( int i = 0; i < 10; i++){BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);// 往person內(nèi)注入屬性,可以注入引用beanDefinitionBuilder.addPropertyValue("name", "admin" + i);beanDefinitionRegistry.registerBeanDefinition("person" + i, beanDefinitionBuilder.getBeanDefinition());}}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {} }

修改App.java

package com.edu.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.edu.spring");context.getBeansOfType(Person.class).values().forEach(person -> {System.out.println(person);});context.close();} }

輸出結(jié)果:

============22 四月 22, 2019 4:38:56 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring ====postProcessBeforeInitialization=====class org.springframework.context.event.EventListenerMethodProcessor ====postProcessAfterInitialization=====class org.springframework.context.event.EventListenerMethodProcessor ====postProcessBeforeInitialization=====class org.springframework.context.event.DefaultEventListenerFactory ====postProcessAfterInitialization=====class org.springframework.context.event.DefaultEventListenerFactory ====postProcessBeforeInitialization=====class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$bc5fcd78 ====postProcessAfterInitialization=====class com.edu.spring.MyConfig$$EnhancerBySpringCGLIB$$bc5fcd78 ====postProcessBeforeInitialization=====class com.edu.spring.User user init ====postProcessAfterInitialization=====class com.edu.spring.User ====postProcessBeforeInitialization=====class com.edu.spring.User ====postProcessAfterInitialization=====class com.edu.spring.User ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person ====postProcessBeforeInitialization=====class com.edu.spring.Person ====postProcessAfterInitialization=====class com.edu.spring.Person Person{name='admin0'} Person{name='admin1'} Person{name='admin2'} Person{name='admin3'} Person{name='admin4'} Person{name='admin5'} Person{name='admin6'} Person{name='admin7'} Person{name='admin8'} Person{name='admin9'}

說明Person自動(dòng)注入進(jìn)去了。

除了這個(gè)方法,也可以使用

AnnotationConfigApplicationContext context.registerBeanDefinition(beanName, beanDefinition);

springboot-1

新建pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.ac.iie</groupId><artifactId>spring-course</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.4.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency></dependencies> </project>

新建App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean;@SpringBootApplication public class App {@Beanpublic Runnable createRunable(){return () -> {System.out.println("spring boot is running");};}public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);context.getBean(Runnable.class).run();} }

運(yùn)行App.java 可以得到輸出結(jié)果如下:

. ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) )' |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot :: (v2.1.4.RELEASE)2019-04-22 22:52:03.868 INFO 11372 --- [ main] com.edu.spring.App : Starting App on duandingyangdeMacBook-Pro.local with PID 11372 (/Users/duandingyang/git-project/springcourse/target/classes started by duandingyang in /Users/duandingyang/git-project/springcourse) 2019-04-22 22:52:03.876 INFO 11372 --- [ main] com.edu.spring.App : No active profile set, falling back to default profiles: default 2019-04-22 22:52:04.651 INFO 11372 --- [ main] com.edu.spring.App : Started App in 1.432 seconds (JVM running for 2.166) spring boot is running

這是一個(gè)最簡單的SpringBoot應(yīng)用。

跟之前的spring使用方法差不多,只是main的入口變了。

在pom.xml文件中,如果我們不想使用parent依賴,應(yīng)該怎么做?

新的pom.xml如下

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.ac.iie</groupId><artifactId>spring-course</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.4.RELEASE</version><scope>import</scope><type>pom</type></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency></dependencies> </project>

在App.java中,點(diǎn)擊查看@SpringBootApplication注釋,有三個(gè)重要的注釋,分別是@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan

目前的情況,我們可以直接使用@ComponentScan注釋就行

App.java如下:

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan;@ComponentScan public class App {@Beanpublic Runnable createRunable(){return () -> {System.out.println("spring boot is running");};}public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);context.getBean(Runnable.class).run();} }

運(yùn)行結(jié)果跟之前是一樣的。

其實(shí)SpringApplication.run(App.class, args)中App.class一般就是入口,也就是配置類,里面可以配置各種Bean。

刪掉@ComponentScan 修改入口配置

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan;public class App {@Beanpublic Runnable createRunable(){return () -> {System.out.println("spring boot is running");};}public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);context.getBean(Runnable.class).run();} }

新建App2.java

package com.edu.spring;import org.springframework.context.annotation.ComponentScan;@ComponentScan public class App2 {}

這樣輸出結(jié)果如下:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Runnable' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)at com.edu.spring.App.main(App.java:21)

因?yàn)檎也坏絙ean,如果將App.java中的生命bean 的代碼剪切到App2.java中,那么程序正常運(yùn)行。

也可以通過這個(gè)方式加載配置類:

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext;import java.util.HashSet; import java.util.Set;public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App2.class);ConfigurableApplicationContext context = application.run(args);context.getBean(Runnable.class).run();}}

新建MyConfig.java

package com.edu.spring;import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean;import java.util.ArrayList; import java.util.List;@SpringBootConfiguration public class MyConfig {@Beanpublic List<String> createList(){ArrayList arrayList = new ArrayList();arrayList.add("a");return arrayList;}}

使用SpringBootConfiguration同樣可以裝配Bean

App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext;import java.util.List;public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App2.class);ConfigurableApplicationContext context = application.run(args);context.getBean(Runnable.class).run();System.out.println(context.getBean(List.class));}}

Springboot配置文件

springboot默認(rèn)的配置文件是application.properties.

新建application.properties,內(nèi)容如下:

local.ip=192.168.1.1 local.port=8080name=springboot app.name=this is ${name}

方法一 使用context.getEnvironment().getProperty("local.ip")

新建App.java,

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.ConfigurableApplicationContext;@SpringBootConfiguration public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getEnvironment().getProperty("local.ip"));context.close();}}

輸出:

192.168.1.1

方法二:

新建UserConfig.java

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component;@Component public class UserConfig {@Autowiredprivate Environment environment;public void show(){System.out.println("local.ip=" + environment.getProperty("local.ip"));}}

修改App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);context.getBean(UserConfig.class).show();context.close();}}

同樣可以輸出local.ip=192.168.1.1

方法三:

修改UserConfig.java, 使用@Value("${local.port}")注釋,來獲取

package com.edu.spring;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component;@Component public class UserConfig {@Value("${local.port}")private String localPort;/*** @Value 默認(rèn)要有配置項(xiàng),配置項(xiàng)可以為空,如果沒有配置項(xiàng),則可以給默認(rèn)值*/@Value("${tomcat.port:9090}")private String tomcatPort;@Autowiredprivate Environment environment;public void show(){System.out.println("local.ip=" + environment.getProperty("local.ip"));System.out.println("local.port=" + localPort);System.out.println("name=" + environment.getProperty("name"));System.out.println("app.name=" + environment.getProperty("app.name"));System.out.println("tomcat.port=" + tomcatPort);}}

使用配置文件引用其他變量

public void show(){System.out.println("local.ip=" + environment.getProperty("local.ip"));System.out.println("local.port=" + localPort);System.out.println("name=" + environment.getProperty("name"));System.out.println("app.name=" + environment.getProperty("app.name"));}

application.properties的位置是resources目錄下(即classpath根目錄)或者是resources/config目錄(即classpath:/config目錄)下。

如果要改application.properties的名字和目錄如何做?

可以在intellij工具 Program argument添加參數(shù) --spring.config.name=文件名 可以省略文件擴(kuò)展名

如果修改目錄 添加參數(shù) --spring.config.location=classpath:conf/app.properties,? 必須指定擴(kuò)展名。還可以指定多個(gè)路徑,用逗號(hào)隔開。之間的指定方式有兩種1.classpath: 2.file:

如果要加載其他配置文件,如何做?

新建jdbc.properties

url=jdbc:mysql:///springboot driverClassName=com.mysql.jdbc.Driver

新建FileConfig.java

package com.edu.spring;import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;@Configuration @PropertySource("classpath:jdbc.properties") public class FileConfig { }

新建JdbcConfig.java

package com.edu.spring;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;@Component public class JdbcConfig {@Value("${url}")private String url;@Value("${driverClassName}")private String driverClassName;public void show(){System.out.println("url=" + url);System.out.println("driverClassName=" + driverClassName);}}

在App.java中

context.getBean(JdbcConfig.class).show();

可以正常輸出。

如果是多個(gè)路徑下的文件,修改FileConfig.java

package com.edu.spring;import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;@Configuration @PropertySource("classpath:jdbc.properties") @PropertySource("file:/e/tmp/jdbc.properties") public class FileConfig { }

或者使用

package com.edu.spring;import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySources;@Configuration @PropertySources({@PropertySource("classpath:jdbc.properties"),@PropertySource("file:/e/tmp/jdbc.properties")}) public class FileConfig { }

新建DataSourceProperties.java

package com.edu.spring;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component;@Component @ConfigurationProperties(prefix = "ds") @PropertySource("classpath:/ds.properties") public class DataSourceProperties {private String url;private String driverClassName;private String username;private String password;public void show(){System.out.println("url:" + url);System.out.println("driverClassName:" + driverClassName);System.out.println("username:" + username);System.out.println("password:" + password);}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getDriverClassName() {return driverClassName;}public void setDriverClassName(String driverClassName) {this.driverClassName = driverClassName;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;} }

新建ds.properties

ds.url=jdbc:mysql:///springboot ds.driverClassName=com.mysql.jdbc.Driver ds.username=root ds.password=123456

springboot 也可以使用application.yml作為配置文件,是使用縮進(jìn)方式書寫。

從配置文件中,注入集合與數(shù)組

新建TomcatProperties.java

package com.edu.spring;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;import java.util.ArrayList; import java.util.Arrays; import java.util.List;@Component @ConfigurationProperties("ds") public class TomcatProperties {private List<String> hosts = new ArrayList<>();private String[] ports;@Overridepublic String toString() {return "TomcatProperties{" +"hosts=" + hosts +", ports=" + Arrays.toString(ports) +'}';}public String[] getPorts() {return ports;}public void setPorts(String[] ports) {this.ports = ports;}public List<String> getHosts() {return hosts;}public void setHosts(List<String> hosts) {this.hosts = hosts;} }

applicatioin.properties

ds.hosts[0]=192.168.1.100 ds.hosts[1]=192.168.1.101 ds.hosts[2]=192.168.1.102 ds.ports[0]=8080 ds.ports[1]=8081 ds.ports[2]=8082

App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getBean(TomcatProperties.class));context.close();}}

注入正常。輸出結(jié)果:

TomcatProperties{hosts=[192.168.1.100, 192.168.1.101, 192.168.1.102], ports=[8080, 8081, 8082]}

動(dòng)態(tài)引入配置文件,使用EnvironmentPostProcessor接口

新建MyEnvironmentPostProcessor.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.stereotype.Component;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Properties;@Component public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {@Overridepublic void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {try(InputStream inputStream = new FileInputStream("F:/test/springboot.properties")){Properties properties = new Properties();properties.load(inputStream);PropertiesPropertySource propertySource = new PropertiesPropertySource("my", properties);environment.getPropertySources().addLast(propertySource);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}} }

測試輸出

System.out.println(context.getEnvironment().getProperty("springboot.name"));

輸出結(jié)果為Null

說明沒有正確注入,在resources目錄下新建META-INF/spring.factories,內(nèi)容如下:

org.springframework.boot.env.EnvironmentPostProcessor=com.edu.spring.MyEnvironmentPostProcessor

執(zhí)行輸出結(jié)果正常。原因是EnvironmentPostProcessor接口不屬于spring的,而是屬于Springboot的,因此需要配置到spring.factories。

有了這一功能我們就可以隨意的增加一些配置了,任意讀取配置,即配置文件中心化

profile,開發(fā)階段和上線測試階段是不同的,如何在不同階段載入不同配置

新建application-dev.properties,內(nèi)容如下

jdbc.url=mysql:jdbc://127.0.0.1/db_springboot_dev

新建application-test.properties,內(nèi)容如下:

jdbc.url=mysql:jdbc://127.0.0.1/db_springboot_test

App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);//application.setAdditionalProfiles("dev");application.setAdditionalProfiles("test");ConfigurableApplicationContext context = application.run(args);System.out.println(context.getBean(TomcatProperties.class));System.out.println(context.getEnvironment().getProperty("springboot.name"));System.out.println(context.getEnvironment().getProperty("jdbc.url"));context.close();}}

這樣就可以實(shí)現(xiàn)切換。默認(rèn)的application.properties也會(huì)加進(jìn)去。

通過啟動(dòng)參數(shù)來控制生效的profile,--spring.profiles.active=test,dev,這樣test和dev便同時(shí)啟用了。

新建MyConfig.java

package com.edu.spring;import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Profile;@SpringBootConfiguration public class MyConfig {@Beanpublic Runnable createRunable(){System.out.println("===1==");return () -> {};}/*** 當(dāng)application-test.properties激活之后才裝配這個(gè)Bean* @return*/@Bean@Profile("test")public Runnable createRunable2(){System.out.println("===2==");return () -> {};}/*** 當(dāng)application-dev.properties激活之后才裝配這個(gè)Bean* @return*/@Bean@Profile("dev")public Runnable createRunable3(){System.out.println("===3==");return () -> {};}}

可以當(dāng)具體properties激活時(shí),裝配Bean。profile注釋也可以用在類上,表示當(dāng)某個(gè)profile生效時(shí),使用這個(gè)類。

spring boot自動(dòng)配置

新建接口EncodingConvert.java

package com.edu.spring;public interface EncodingConvert {}

新建實(shí)現(xiàn)類GBKEncodingConvert.java

public class GBKEncodingConvert implements EncodingConvert { }

新建實(shí)現(xiàn)類UTF8EncodingConvert.java

package com.edu.spring;public class UTF8EncodingConvert implements EncodingConvert { }

新建EncodingConvertConfig.java

package com.edu.spring;import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean;@SpringBootConfiguration public class EncodingConvertConfig {@Beanpublic EncodingConvert createUTF8EncodingConvert(){return new UTF8EncodingConvert();}@Beanpublic EncodingConvert createGBKEncodingConvert(){return new GBKEncodingConvert();}}

新建App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(System.getProperty("file.encoding"));System.out.println(context.getBeansOfType(EncodingConvert.class));context.close();}}

運(yùn)行App.java,打印輸出結(jié)果如下:

{createUTF8EncodingConvert=com.edu.spring.UTF8EncodingConvert@c9d0d6, createGBKEncodingConvert=com.edu.spring.GBKEncodingConvert@6ccdb29f}

兩個(gè)Bean都裝配成功。

新建GBKCondition.java

package com.edu.spring;import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata;public class GBKCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {String encoding = System.getProperty("file.encoding");if(encoding != null){return "gbk".equals(encoding.toLowerCase());}return false;} }

新建UTF8Condition.java

package com.edu.spring;import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata;public class UTF8Condition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {String encoding = System.getProperty("file.encoding");if(encoding != null){return "utf-8".equals(encoding.toLowerCase());}return false;} }

在intellij 的VMoption參數(shù)添加 -Dfile.encoding=GBK

打印輸出:

{createGBKEncodingConvert=com.edu.spring.GBKEncodingConvert@512baff6}

@Conditional 是基于條件的自動(dòng)配置,一般配合Condition接口一起使用,只有接口(一個(gè)或多個(gè))實(shí)現(xiàn)類都返回true才裝配,否則不裝配。

它可以用在方法上,則只對(duì)該方法起作用,還可以用在類上,則對(duì)該類的所有方法起作用。

此外,@Conditional({UTF8Condition.class, GBKCondition.class}),表示兩個(gè)條件都返回true才生效。

@ConditionalOnProperty,表示某個(gè)屬性等于某個(gè)值時(shí)。

新建UserConfiguration.java

package com.edu.spring;import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean;@SpringBootConfiguration public class UserConfiguration {@Bean@ConditionalOnProperty(name = "runnable.enabled", havingValue = "true")public Runnable createRunnable(){return ()->{};}}

當(dāng)application.properties中的屬性runnable.enabled=true時(shí),這個(gè)Bean才能夠裝配。否則裝配不成功。matchIfMissing表示當(dāng)這個(gè)配置不存在的時(shí)候,也為true。

修改UserConfiguration.java

package com.edu.spring;import com.google.gson.Gson; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean;@SpringBootConfiguration public class UserConfiguration {@Bean@ConditionalOnProperty(name = "runnable.enabled", havingValue = "true", matchIfMissing = true)public Runnable createRunnable() {return () -> {};}@Bean@ConditionalOnClass(name = "com.google.gson.Gson")public Runnable createGsonRunnable() {return () -> {};}}

修改pom.xml,添加gson依賴

<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.1</version></dependency>

@ConditionalOnClass表示當(dāng)存在這個(gè)“com.google.gson.Gson”類的時(shí)候,就裝配這個(gè)Bean。

@ConditionalOnMissingClass表示當(dāng)不存在這個(gè)“com.google.gson.Gson”類的時(shí)候,就裝配這個(gè)Bean。

打印輸出:

{createRunnable=com.edu.spring.UserConfiguration$$Lambda$137/800735172@335b5620, createGsonRunnable=com.edu.spring.UserConfiguration$$Lambda$138/478489615@29a0cdb}

去掉pom.xml中的依賴是,就不會(huì)裝配這個(gè)bean。

@ConditionalOnBean??根據(jù)容器中存在某個(gè)bean來進(jìn)行裝配

修改UserConfiguration.java

@Bean@ConditionalOnBean(name="user")public Runnable createBeanRunnable() {return () -> {};}

運(yùn)行時(shí)輸出:

{createRunnable=com.edu.spring.UserConfiguration$$Lambda$137/698741991@22356acd, createGsonRunnable=com.edu.spring.UserConfiguration$$Lambda$138/669284403@386f0da3}

沒有輸出createBeanRunnable這個(gè)Bean,添加User.java

package com.edu.spring;import org.springframework.stereotype.Component;@Component public class User { }

然后運(yùn)行輸出:

{createRunnable=com.edu.spring.UserConfiguration$$Lambda$138/1934932165@27d4a09, createGsonRunnable=com.edu.spring.UserConfiguration$$Lambda$139/1508038883@7e4204e2, createBeanRunnable=com.edu.spring.UserConfiguration$$Lambda$140/728943498@b7c4869}

說明成功配置了createBeanRunnable這個(gè)bean了。

@ConditionalOnMissiongBean??根據(jù)容器中不存在某個(gè)bean來進(jìn)行裝配

Spring Boot @Enable*注解工作原理

新建TomcatProperties.java

package com.edu.spring;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component;@Component @ConfigurationProperties(prefix = "tomcat") public class TomcatProperties {private String host;private String port;@Overridepublic String toString() {return "TomcatProperties{" +"host='" + host + '\'' +", port='" + port + '\'' +'}';}public String getHost() {return host;}public void setHost(String host) {this.host = host;}public String getPort() {return port;}public void setPort(String port) {this.port = port;} }

application.properties

tomcat.host=192.168.1.100 tomcat.port=8080

新建App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getBean(TomcatProperties.class));context.close();}}

運(yùn)行輸出結(jié)果:

TomcatProperties{host='192.168.1.100', port='8080'}

當(dāng)我們修改App.java的注解時(shí),

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan;/*** @EnableConfiguratinProperties是用來啟用一個(gè)特性的,這個(gè)特性可以把配置文件的屬性注入到bean里面去*/ @EnableConfigurationProperties @ComponentScan public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getBean(TomcatProperties.class));context.close();}}

程序也可以正常運(yùn)行,但是當(dāng)我們將注解@EnableConfiguratinProperties刪掉后,程序就獲取不到properties的內(nèi)容了。說明是@EnableConfiguratinProperties起了作用。

如何在Springboot中啟動(dòng)異步?

新建Jeep.java

package com.edu.spring;import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component public class Jeep implements Runnable {@Overridepublic void run() {try {for(int i = 1; i<= 10; i++){System.out.println("============" + i);TimeUnit.SECONDS.sleep(1);}}catch (Exception e){e.printStackTrace();}} }

修改App.java

context.getBean(Runnable.class).run(); System.out.println("----end-----");

輸出結(jié)果如下:

TomcatProperties{host='192.168.1.100', port='8080'} ============1 ============2 ============3 ============4 ============5 ============6 ============7 ============8 ============9 ============10 ----end-----

說明當(dāng)run方法執(zhí)行完之后,才輸出end。如何實(shí)現(xiàn)異步?

在App.java上啟動(dòng)異步,添加注釋:

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync;/*** @EnableConfiguratinProperties是用來啟用一個(gè)特性的,這個(gè)特性可以把配置文件的屬性注入到bean里面去,一般是和@ConfigurationProperties一起使用* @EnableAsync 啟用異步,一般是和@Async一起使用*/ @EnableConfigurationProperties @EnableAsync @ComponentScan public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getBean(TomcatProperties.class));context.getBean(Runnable.class).run();System.out.println("----end-----");context.close();}}

在Jeep.java的run方法上添加@Async注釋

package com.edu.spring;import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component public class Jeep implements Runnable {@Async@Overridepublic void run() {try {for(int i = 1; i<= 10; i++){System.out.println("============" + i);TimeUnit.SECONDS.sleep(1);}}catch (Exception e){e.printStackTrace();}} }

運(yùn)行輸出結(jié)果如下:

----end----- ============1 ============2 ============3 ============4 ============5 ============6 ============7 ============8 ============9 ============10

說明已經(jīng)成功異步了。

新建User.java

package com.edu.spring;public class User { }

新建Role.java

package com.edu.spring;public class Role { }

新建App2.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan;@ComponentScan public class App2 {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);context.close();}}

此時(shí)App2.java中無法獲取User的Bean和Role的Bean,想獲取的方式是:有很多,之前有講過,例如:@Component。今天講另一種方式:

修改App2.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import;@ComponentScan @Import(User.class) public class App2 {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);System.out.println(context.getBean(User.class));context.close();}}

添加Import注釋,這樣就可以使用User的Bean了。

@Import注釋也可以導(dǎo)入一個(gè)數(shù)組,例如:@Import({User.class, Role.class})

此外,@Import還可以到如配置類

新建MyConfiguration.java

package com.edu.spring;import org.springframework.context.annotation.Bean;public class MyConfiguration {@Beanpublic Runnable createRunnable(){return () -> {};}@Beanpublic Runnable createRunnable2(){return () -> {};}}

修改App2.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import;/*** @Import 用來導(dǎo)入一個(gè)或多個(gè)類(Bean會(huì)被Spring容器托管),或者配置類(配置類里面的bean會(huì)被Spring容器托管)*/ @ComponentScan @Import({User.class, Role.class, MyConfiguration.class}) public class App2 {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);System.out.println(context.getBean(User.class));System.out.println(context.getBeansOfType(Runnable.class));context.close();} }

使用Import導(dǎo)入MyConfiguration,輸出結(jié)果:

com.edu.spring.User@6f27a732 {jeep=com.edu.spring.Jeep@6c779568, createRunnable=com.edu.spring.MyConfiguration$$Lambda$93/1730704097@f381794, createRunnable2=com.edu.spring.MyConfiguration$$Lambda$94/726379593@2cdd0d4b}

說明成功導(dǎo)入了配置類。

ImportSelector是什么?

新建MyImportSelector.java

package com.edu.spring;import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata;/*** ImportSelector的方法的返回值,必須是一個(gè)class(全稱),該class會(huì)被spring容器托管起來。*/ public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.edu.spring.User",Role.class.getName(), MyConfiguration.class.getName()};} }

修改App2.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import;/*** @Import 用來導(dǎo)入一個(gè)或多個(gè)類(Bean會(huì)被Spring容器托管),或者配置類(配置類里面的bean會(huì)被Spring容器托管)*/ @ComponentScan //@Import({User.class, Role.class, MyConfiguration.class}) @Import(MyImportSelector.class) public class App2 {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);System.out.println(context.getBean(User.class));System.out.println(context.getBean(Role.class));System.out.println(context.getBeansOfType(Runnable.class));context.close();}}

同樣可以輸出User的Bean,Role的Bean以及Runnable的Bean,說明裝配成功。

新建EnableLog.java

package com.edu.spring;import org.springframework.context.annotation.Import;import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MyImportSelector.class) public @interface EnableLog {String name(); }

在MyImportSelector.java中修改:

package com.edu.spring;import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata;/*** ImportSelector的方法的返回值,必須是一個(gè)class(全稱),該class會(huì)被spring容器托管起來。*/ public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {System.out.println(importingClassMetadata.getAllAnnotationAttributes(EnableLog.class.getName()));/*** 這里可以獲取到注解的詳細(xì)信息。然后根據(jù)信息去動(dòng)態(tài)的返回需要被spring容器管理的bean*/return new String[]{"com.edu.spring.User",Role.class.getName(), MyConfiguration.class.getName()};} }

可以輸出注釋的信息。

修改APP2.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import;/*** @Import 用來導(dǎo)入一個(gè)或多個(gè)類(Bean會(huì)被Spring容器托管),或者配置類(配置類里面的bean會(huì)被Spring容器托管)*/ @ComponentScan //@Import({User.class, Role.class, MyConfiguration.class}) @Import(MyImportSelector.class) @EnableLog(name="my springboot") public class App2 {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);System.out.println(context.getBean(User.class));System.out.println(context.getBean(Role.class));System.out.println(context.getBeansOfType(Runnable.class));context.close();}}

輸出結(jié)果可以輸出{name=[my springboot]},可以獲取到注解的詳細(xì)信息

@EnableAutoConfiguration深入分析

新建App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getBean(Runnable.class));context.close();} }

運(yùn)行報(bào)錯(cuò),因?yàn)闆]有Runnable這個(gè)bean。

新建項(xiàng)目:corebean

pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.edu.core</groupId><artifactId>core-bean</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.6.RELEASE</version></dependency></dependencies></project>

新建RunnableConfiguration.java

package com.edu.core.bean;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class RunnableConfiguration {@Beanpublic Runnable createRunnable(){return () -> {};}}

在springcourse項(xiàng)目的pom.xml中添加corebean項(xiàng)目依賴:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.ac.iie</groupId><artifactId>spring-course</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.4.RELEASE</version><scope>import</scope><type>pom</type></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>com.edu.core</groupId><artifactId>core-bean</artifactId><version>1.0.0</version></dependency></dependencies> </project>

在次運(yùn)行App.java

同樣顯示沒有找到Runnable的bean類。

如果spring只支持當(dāng)前項(xiàng)目中加載配置,那么他的擴(kuò)展性太不好了,如何解決這個(gè)第三方j(luò)ar的配置?

使用EnableAutoConfiguration注解

修改App.java,我們只用@EnableAutoConfiguration和@ComponentScan注釋

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan;/*** EnableAutoConfiguration 作用:從classpath中搜索所有META-INF/spring.factories配置文件,* 然后,將其中org.springframework.boot.autoconfigure.EnableAutoConfiguration key對(duì)應(yīng)的配置項(xiàng)加載到spring容器中*/ @EnableAutoConfiguration @ComponentScan public class App {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(App.class, args);System.out.println(context.getBean(Runnable.class));context.close();} }

在resources目錄下創(chuàng)建META-INF/spring.factories,內(nèi)容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.edu.core.bean.RunnableConfiguration

運(yùn)行App.java,輸出如下:

com.edu.core.bean.RunnableConfiguration$$Lambda$134/549293029@398dada8

成功注入進(jìn)去了Runnable的Bean。

如何配置多個(gè)?

在core-bean中新建User.java和Role.java以及一個(gè)配置類UserConfiguration.java內(nèi)容分別如下:

package com.edu.core.bean;public class User { } package com.edu.core.bean;public class Role { } package com.edu.core.bean;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class UserConfiguration {@Beanpublic User createUser(){return new User();} }

然后在springcourse的spring.factories中內(nèi)容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.edu.core.bean.RunnableConfiguration,com.edu.core.bean.UserConfiguration,com.edu.core.bean.Role

同樣成功注入進(jìn)去了。這樣就實(shí)現(xiàn)了添加多個(gè)配置類。

只有在application.properties 文件中,spring.boot.enableautoconfiguration為true(默認(rèn)為true)時(shí),才啟用自動(dòng)配置。默認(rèn)不用配置時(shí)為true

其內(nèi)部實(shí)現(xiàn)的關(guān)鍵點(diǎn)有:
?1. ImportSelector 該接口的方法的額返回值都會(huì)被納入到spring容器管理中
?2. SpringFactoriesLoader 該類可以從classpath中搜索所有META-INF/spring.factories配置文件,并讀取配置

?如果想要排除某些類,應(yīng)該如何做?

方式一:通過class來排除

使用exclude

使用@EnableAutoConfiguration(exclude = UserConfiguration.class) 就將User的bean排除在外了。

方式二:通過類名來排除

使用@EnableAutoConfiguration(excludeName = "com.edu.core.bean.Role")

Springboot 事件監(jiān)聽

事件流程:

? ? 1. 自定義事件,一般是繼承ApplicationEvent抽象類

? ? 2. 定義時(shí)間監(jiān)聽器,一般是實(shí)現(xiàn)ApplicationListener接口

? ? 3. 啟動(dòng)的時(shí)候,需要把監(jiān)聽器加入到spring容器中

? ? 4. 發(fā)布事件,使用ApplicationContext的publishEvent發(fā)布事件

? ? 5. 配置監(jiān)聽器

????? ? a. SpringApplication.addListeners 添加監(jiān)聽器

????? ? b. 把監(jiān)聽器納入到spring容器中管理 @Component

????? ? c. 可以使用配置項(xiàng),在application.properties中配置context.listener.classes=com.edu.spring.MyApplicationListener? ?詳細(xì)內(nèi)容參數(shù):DelegatingApplicationListener

定義事件,新建MyApplicationEvent.java

package com.edu.spring;import org.springframework.context.ApplicationEvent;/*** 定義事件*/ public class MyApplicationEvent extends ApplicationEvent {public MyApplicationEvent(Object source) {super(source);} }

定義監(jiān)聽器,MyApplicationListener.java

package com.edu.spring;import org.springframework.context.ApplicationListener;public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {@Overridepublic void onApplicationEvent(MyApplicationEvent event) {System.out.println("接收到事件:" + event.getClass());} }

新建App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan;@EnableAutoConfiguration(excludeName = "com.edu.core.bean.Role") @ComponentScan public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);application.addListeners(new MyApplicationListener());ConfigurableApplicationContext context = application.run(args);//發(fā)布事件context.publishEvent(new MyApplicationEvent(new Object()));context.close();} }

運(yùn)行結(jié)果:

接收到事件:class com.edu.spring.MyApplicationEvent

說明監(jiān)聽成功。

除了使用application.addListeners(new MyApplicationListener());這種方式添加監(jiān)聽器,還有什么方式?

可以使用@Component注釋給MyApplicationListener.java。這樣也可以。

另一種方式配置監(jiān)聽器:新建MyEventHandler.java

package com.edu.spring;import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component;@Component public class MyEventHandle {/*** 參數(shù)一定要是ApplicationEvent,或者其子類* @param event*/@EventListenerpublic void event(MyApplicationEvent event){System.out.println("接受到事件" + event.getClass());}}

使用注解@EventListener也可以配置監(jiān)聽器,且該類需要納入到spring容器重管理(詳細(xì)內(nèi)容參照EventListenerFactory和EventListenerMethodProcessor),不用其他的配置了。如果參數(shù)設(shè)置成public void event(Object event) 那么所有的事件都能夠接收到。?

spring或者Springboot內(nèi)部有哪些已經(jīng)定義好的事件?

修改MyEventHandle.java

package com.edu.spring;import org.springframework.context.event.ContextStoppedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component;@Component public class MyEventHandle {/*** 參數(shù)一定要是ApplicationEvent,或者其子類* @param event*/@EventListenerpublic void event(MyApplicationEvent event){System.out.println("接受到事件" + event.getClass());}@EventListenerpublic void event2(ContextStoppedEvent event){System.out.println("應(yīng)用停止事件:" + event);}}

在App.java中修改:

context.publishEvent(new MyApplicationEvent(new Object()));

輸出結(jié)果:

接受到事件class com.edu.spring.MyApplicationEvent 應(yīng)用停止事件:org.springframework.context.event.ContextStoppedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@314c508a, started on Thu Apr 25 17:07:00 CST 2019]

監(jiān)聽器起作用了。

spring boot擴(kuò)展分析

新建MyApplicationContextInitializer.java

package com.edu.spring;import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext;public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("bean count: " + applicationContext.getBeanDefinitionCount());} }

新建MyApplicationContextInitializer2.java

package com.edu.spring;import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext;public class MyApplicationContextInitializer2 implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("app name: " + applicationContext.getDisplayName());} }

新建App.java

package com.edu.spring;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);application.addInitializers(new MyApplicationContextInitializer());ConfigurableApplicationContext context = application.run(args);context.stop();context.close();} }

在application.properties中內(nèi)容如下:

context.initializer.classes=com.edu.spring.MyApplicationContextInitializer, com.edu.spring.MyApplicationContextInitializer2

運(yùn)行App.java

輸出結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@1a052a00

ApplicationContextInitializer 接口是在spring容器執(zhí)行refreshed之前的一個(gè)回調(diào)
?使用步驟:
? ? ?1. 寫一個(gè)類,實(shí)現(xiàn)ApplicationContextInitializer接口
? ? ?2. 注冊(cè)ApplicationContextInitializer

?注冊(cè)方法:
? ? ?1. SpringApplication.addInitializers()
? ? ?2. 通過application.properties 配置context.initializer.classes=com.edu.spring.MyApplicationContextInitializer來進(jìn)行,可以指定多個(gè),多個(gè)用逗號(hào)隔開
? ? ?3. 通過spring.factories機(jī)制,(注冊(cè)listener監(jiān)聽器也可以使用這種方式)

下面詳細(xì)說明如何通過spring.factories實(shí)現(xiàn)。

新建項(xiàng)目initializer。

其中pom.xml內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.edu.spring</groupId><artifactId>initializer</artifactId><version>1.0-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.4.RELEASE</version><scope>import</scope><type>pom</type></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency></dependencies></project>

新建EchoApplicationContextInitializer.java

package com.edu.spring.initializer;import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext;public class EchoApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext configurableApplicationContext) {System.out.println("===EchoApplicationContextInitializer====");} }

在resources下新建META-INF/spring.factories,內(nèi)容如下:

org.springframework.context.ApplicationContextInitializer=com.edu.spring.initializer.EchoApplicationContextInitializer

然后在springcourse項(xiàng)目的pom中導(dǎo)入Initializer項(xiàng)目

<dependency><groupId>com.edu.spring</groupId><artifactId>initializer</artifactId><version>1.0-SNAPSHOT</version></dependency>

運(yùn)行App.java,執(zhí)行結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@ca263c2 ===EchoApplicationContextInitializer====

說明成功注入。

CommandLineRunner接口回調(diào)

在springboot項(xiàng)目中,新建ServerSuccessReport.java

package com.edu.spring;import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component;@Component public class ServerSuccessReport implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("=====應(yīng)用已經(jīng)成功啟動(dòng)=====");} }

運(yùn)行結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@27c6e487 ===EchoApplicationContextInitializer==== 2019-04-26 15:33:13.441 INFO 1396 --- [ main] com.edu.spring.App : Starting App on DESKTOP-AQM2529 with PID 1396 (E:\git\springcourse\target\classes started by vincent in E:\git\springcourse) 2019-04-26 15:33:13.443 INFO 1396 --- [ main] com.edu.spring.App : No active profile set, falling back to default profiles: default 2019-04-26 15:33:14.150 INFO 1396 --- [ main] com.edu.spring.App : Started App in 1.013 seconds (JVM running for 1.577) =====應(yīng)用已經(jīng)成功啟動(dòng)=====

從輸出結(jié)果中可以看到,在Started App啟動(dòng)之后,輸出CommandLineRunner接口方法。

CommandLineRunner ApplicationRunner接口是在容器啟動(dòng)成功后的最后一步的回調(diào)。類似開機(jī)自啟動(dòng)

使用步驟:

? ? 1. 寫一個(gè)類,實(shí)現(xiàn)CommandLineRunner接口

? ? 2. 把該類納入到Spring容器中

? ? 3. 可以通過@Order注解或者Ordered接口來控制執(zhí)行順序

如果有多個(gè)類實(shí)現(xiàn)了CommandLineRunner接口,如何保證執(zhí)行順序?

新建ServerStartedReport.java

package com.edu.spring;import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component public class ServerStartedReport implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("=========應(yīng)用啟動(dòng)后的時(shí)間是:" + LocalDateTime.now().toString());} }

運(yùn)行App.java,結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@7ff2a664 ===EchoApplicationContextInitializer==== 2019-04-26 15:44:03.081 INFO 2656 --- [ main] com.edu.spring.App : Starting App on DESKTOP-AQM2529 with PID 2656 (E:\git\springcourse\target\classes started by vincent in E:\git\springcourse) 2019-04-26 15:44:03.084 INFO 2656 --- [ main] com.edu.spring.App : No active profile set, falling back to default profiles: default 2019-04-26 15:44:03.775 INFO 2656 --- [ main] com.edu.spring.App : Started App in 1.0 seconds (JVM running for 1.426) =========應(yīng)用啟動(dòng)后的時(shí)間是:2019-04-26T15:44:03.784 =====應(yīng)用已經(jīng)成功啟動(dòng)=====

如果我們想要ServerSuccessReport類先執(zhí)行,可以使用@Order注釋。

@Order(3) @Component public class ServerStartedReport implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("=========應(yīng)用啟動(dòng)后的時(shí)間是:" + LocalDateTime.now().toString());} } @Order(2) @Component public class ServerSuccessReport implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("=====應(yīng)用已經(jīng)成功啟動(dòng)=====");} }

只要Order括號(hào)內(nèi)的數(shù)字越小,則越先執(zhí)行。

新建StartedApplicationRunner.java

package com.edu.spring;import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component;import java.util.Arrays;@Component public class StartedApplicationRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {System.out.println("應(yīng)用已經(jīng)啟動(dòng),參數(shù)為:" + Arrays.deepHashCode(args.getSourceArgs()));} }

修改ServerSuccessReport.java的輸出

@Overridepublic void run(String... args) throws Exception {System.out.println("=====應(yīng)用已經(jīng)成功啟動(dòng)=====" + Arrays.asList(args));}

App.java添加參數(shù):

@SpringBootApplication public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);//application.addInitializers(new MyApplicationContextInitializer());ConfigurableApplicationContext context = application.run("aa", "bb");context.stop();context.close();} }

運(yùn)行App.java,結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@78a2da20 ===EchoApplicationContextInitializer==== 2019-04-26 16:04:07.136 INFO 1684 --- [ main] com.edu.spring.App : Starting App on DESKTOP-AQM2529 with PID 1684 (E:\git\springcourse\target\classes started by vincent in E:\git\springcourse) 2019-04-26 16:04:07.138 INFO 1684 --- [ main] com.edu.spring.App : No active profile set, falling back to default profiles: default 2019-04-26 16:04:07.832 INFO 1684 --- [ main] com.edu.spring.App : Started App in 0.994 seconds (JVM running for 1.458) =====應(yīng)用已經(jīng)成功啟動(dòng)=====[aa, bb] =========應(yīng)用啟動(dòng)后的時(shí)間是:2019-04-26T16:04:07.844 應(yīng)用已經(jīng)啟動(dòng),參數(shù)為:[aa, bb]

CommandLineRunner ApplicationRunner區(qū)別:

區(qū)別在于方法的參數(shù)不一樣,CommandLineRunner的參數(shù)為最原始參數(shù),沒有做任何處理,ApplicationRunner的參數(shù)是ApplicationArguments,是對(duì)原始參數(shù)做了進(jìn)一步的封裝。

進(jìn)一步說明ApplicationArguments的作用。

修改App.java

@SpringBootApplication public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);//application.addInitializers(new MyApplicationContextInitializer());ConfigurableApplicationContext context = application.run(args);ApplicationArguments arguments = context.getBean(ApplicationArguments.class);System.out.println(arguments.getSourceArgs().length);System.out.println(arguments.getOptionNames());System.out.println(arguments.getOptionValues("myname"));context.stop();context.close();} }

修改Intellij 的運(yùn)行參數(shù),Program arguments 為 --myname admin,運(yùn)行輸出結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@6a79c292 ===EchoApplicationContextInitializer==== 2019-04-26 16:19:12.343 INFO 8216 --- [ main] com.edu.spring.App : Starting App on DESKTOP-AQM2529 with PID 8216 (E:\git\springcourse\target\classes started by vincent in E:\git\springcourse) 2019-04-26 16:19:12.346 INFO 8216 --- [ main] com.edu.spring.App : No active profile set, falling back to default profiles: default 2019-04-26 16:19:13.001 INFO 8216 --- [ main] com.edu.spring.App : Started App in 0.959 seconds (JVM running for 1.401) =====應(yīng)用已經(jīng)成功啟動(dòng)=====[--myname, admin] =========應(yīng)用啟動(dòng)后的時(shí)間是:2019-04-26T16:19:13.010 應(yīng)用已經(jīng)啟動(dòng),參數(shù)為:[--myname, admin] 2 [myname] []

修改Intellij 的運(yùn)行參數(shù),Program arguments 為 --myname=admin,運(yùn)行輸出結(jié)果如下:

bean count: 5 app name: org.springframework.context.annotation.AnnotationConfigApplicationContext@78a2da20 ===EchoApplicationContextInitializer==== 2019-04-26 16:20:08.312 INFO 11652 --- [ main] com.edu.spring.App : Starting App on DESKTOP-AQM2529 with PID 11652 (E:\git\springcourse\target\classes started by vincent in E:\git\springcourse) 2019-04-26 16:20:08.315 INFO 11652 --- [ main] com.edu.spring.App : No active profile set, falling back to default profiles: default 2019-04-26 16:20:08.956 INFO 11652 --- [ main] com.edu.spring.App : Started App in 0.939 seconds (JVM running for 1.469) =====應(yīng)用已經(jīng)成功啟動(dòng)=====[--myname=admin] =========應(yīng)用啟動(dòng)后的時(shí)間是:2019-04-26T16:20:08.961 應(yīng)用已經(jīng)啟動(dòng),參數(shù)為:[--myname=admin] 1 [myname] [admin]

ApplicationArguments是對(duì)參數(shù)(main方法),做了進(jìn)一步處理

可以解析 --name=value的,我們就可以通過name來獲取value。如果我們用原始的方法進(jìn)行獲取參數(shù)時(shí),還得需要對(duì)參數(shù)進(jìn)行分割。

Springboot補(bǔ)充講解

我們知道@SpringBootApplication注解有三個(gè)注解所組成的,分別是:@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan

在com.edu.spring.springboot包下面新建App.java

package com.edu.spring.springboot;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);ConfigurableApplicationContext context = application.run(args);System.out.println(context.getBean(Runnable.class));context.close();} }

在com.edu.spring.bean包下新建RunnableConfiguration.java

package com.edu.spring.bean;import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean;@SpringBootConfiguration public class RunnableConfiguration {@Beanpublic Runnable createRunnable(){return ()->{};}}

運(yùn)行App.java輸出結(jié)果如下:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Runnable' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)at com.edu.spring.springboot.App.main(App.java:13)

說明沒有成功注入。原因是@SpringBootApplication掃描的是當(dāng)前包和子包下面的所有類。但是同一級(jí)的包是無法掃描到的。可以通過basePackage來指定。修改App.java如下:

package com.edu.spring.springboot;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication(scanBasePackages = "com.edu.spring") public class App {public static void main(String[] args) {SpringApplication application = new SpringApplication(App.class);ConfigurableApplicationContext context = application.run(args);System.out.println(context.getBean(Runnable.class));context.close();} }

這樣就成功注入了。

排除某些類,方法如下:

修改pom.xml,添加gson依賴。

<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId></dependency>

因?yàn)間son依賴,已經(jīng)在springboot父類中定義,所以不需要指定version。

修改RunnableConfiguration.java

@Beanpublic Gson createGson(){return new Gson();}

修改App.java

System.out.println(context.getBean(Gson.class));

輸出結(jié)果正常。說明成功注入進(jìn)去。

排除Gson的bean。修改App.java

@SpringBootApplication(scanBasePackages = "com.edu.spring", exclude = GsonAutoConfiguration.class)

沒有排除掉,目前這有問題。

排除指定類、配置類,exclude:根據(jù)class來排除,excludeName:根據(jù)class name來排除。

自定義Banner方法

我們每次輸出的時(shí)候都會(huì)輸出spring的Banner:

. ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) )' |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/

如何控制不輸出呢?

修改App.java如下:

SpringApplication application = new SpringApplication(App.class); application.setBannerMode(Banner.Mode.OFF);

這樣就不輸出Spring的Banner了。

還可以自定義Banner,在resources目錄下新建banner.txt

然后就可以執(zhí)行成功了。注意不要把Banner.Mode.OFF開啟。

第二種方式自定義Banner的方法是,在application.properties文件中寫文件路徑。支持圖片的Banner,圖片的格式支持jpg,png,gif

spring.banner.location=banner2.txt spring.banner.image.location=banner2.jpg

讀取application.properties時(shí)如果沒有key則獲取默認(rèn)的value,方法如下:

方法一:在@value注釋上使用默認(rèn)的value

@Value(("${server.host:localhost}"))private String serverHosts;

方法二:使用getProperty方法:

System.out.println(context.getEnvironment().getProperty("server.host2","localhost2"));

spring boot 運(yùn)行流程分析

spingboot的執(zhí)行入口有兩個(gè)分別是:

// 實(shí)例化SpringApplication對(duì)象,然后調(diào)用run方法 SpringApplication application = new SpringApplication(App.class); ConfigurableApplicationContext context = application.run(args); // 直接調(diào)用靜態(tài)run方法(內(nèi)部轉(zhuǎn)換成第一種調(diào)用方式) ConfigurableApplicationContext context = SpringApplication.run(App.class, args);

? 運(yùn)行流程
? ?1. 判斷是否是web環(huán)境
? ?2. 加載所有classpath下面的META-INF/spring.factories, ?ApplicationContextInitializerr
? ?3. 加載所有classpath下面的META-INF/spring.factories, ApplicationListener
? ?4. 推斷main方法所在的類
? ?5. 開始執(zhí)行run方法
? ?6. 設(shè)置java.awt.headless系統(tǒng)變量
? ?7. 加載所有classpath下面的META-INF/spring.factories SpringApplicationRunListener
? ?8. 執(zhí)行所有SpringApplicationRunListener的started方法
? ?9. 實(shí)例化ApplicationArguments對(duì)象
? ?10. 創(chuàng)建Environment
? ?11. 配置Environment,主要是把run方法的參數(shù)配置到Environment
? ?12. 執(zhí)行所有SpringApplicationRunListener的environment.prepared方法
? ?13. 如果不是web環(huán)境,但是是web的Environment,則把web的Environment轉(zhuǎn)換成標(biāo)準(zhǔn)的Environment
? ?14. 輸出Banner
? ?15. 初始化applicationContext,如果是web環(huán)境,則實(shí)例化AnnotationConfigEmbeddedWebApplicationContext對(duì)象,否則實(shí)例化AnnotationConfigApplicationContext對(duì)象
? ?16. 如果beanNameGenerator不為空,就把beanNameGenerator對(duì)象注入Context里面去
? ?17. 回調(diào)所有的ApplicationContextInitializer方法
? ?18. 執(zhí)行所有SpringApplicationRunListener的contextPrepared方法
? ?19. 依次往Spring容器中注入:ApplicationArguments, Banner
? ?20. 加載所有的源到context里面去。
? ?21. 執(zhí)行所有SpringApplicationRunListener的contextLoaded方法
? ?22. 執(zhí)行context的refresh方法,并且調(diào)用context的registerShutdownHook方法
? ?23. 回調(diào),獲取容器中所有的ApplicationRunner, CommandLineRunner接口,然后排序,依次調(diào)用
? ?24. 執(zhí)行所有SpringApplicationRunListener的finished的finished方法

總結(jié)

以上是生活随笔為你收集整理的springboot教程(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

国产精品免费大片 | 亚洲欧美精品伊人久久 | 欧美阿v高清资源不卡在线播放 | 国产精品-区区久久久狼 | 影音先锋中文字幕无码 | 高潮毛片无遮挡高清免费视频 | www一区二区www免费 | 精品亚洲韩国一区二区三区 | 午夜肉伦伦影院 | 学生妹亚洲一区二区 | 色老头在线一区二区三区 | 精品无码国产自产拍在线观看蜜 | 国产 精品 自在自线 | 无码精品国产va在线观看dvd | 亚洲一区二区三区 | 久久99精品国产.久久久久 | 图片小说视频一区二区 | 亚洲 a v无 码免 费 成 人 a v | 丰满护士巨好爽好大乳 | 捆绑白丝粉色jk震动捧喷白浆 | 熟女体下毛毛黑森林 | 国产av一区二区精品久久凹凸 | 人人妻人人澡人人爽人人精品 | 国语自产偷拍精品视频偷 | 国产区女主播在线观看 | 色综合久久久无码中文字幕 | 国产两女互慰高潮视频在线观看 | 中文字幕 人妻熟女 | 人人妻人人藻人人爽欧美一区 | 亚洲国产精品久久人人爱 | 黑人巨大精品欧美一区二区 | 欧美日本免费一区二区三区 | 一个人免费观看的www视频 | 无码人妻少妇伦在线电影 | 西西人体www44rt大胆高清 | 内射白嫩少妇超碰 | 无码国产乱人伦偷精品视频 | 久久午夜无码鲁丝片秋霞 | 少妇被粗大的猛进出69影院 | 国产真人无遮挡作爱免费视频 | 图片区 小说区 区 亚洲五月 | 老熟女乱子伦 | 亚洲第一网站男人都懂 | 国产精品a成v人在线播放 | 国产三级久久久精品麻豆三级 | 国产精品高潮呻吟av久久 | 午夜时刻免费入口 | 国产激情精品一区二区三区 | 水蜜桃色314在线观看 | 久久久久亚洲精品中文字幕 | 亚洲の无码国产の无码步美 | 亚洲熟妇色xxxxx欧美老妇y | 成人综合网亚洲伊人 | 草草网站影院白丝内射 | 国产97人人超碰caoprom | 在线天堂新版最新版在线8 | 久久久久免费看成人影片 | 成人av无码一区二区三区 | 国产一区二区三区影院 | 国产亚洲人成在线播放 | www国产亚洲精品久久久日本 | 精品无码一区二区三区的天堂 | 精品国产一区二区三区av 性色 | 国产麻豆精品精东影业av网站 | 亚洲国产日韩a在线播放 | 成人欧美一区二区三区黑人 | 国内精品久久久久久中文字幕 | 国产凸凹视频一区二区 | 性做久久久久久久久 | 国产xxx69麻豆国语对白 | 精品久久综合1区2区3区激情 | 久9re热视频这里只有精品 | 女人和拘做爰正片视频 | 久久久久久av无码免费看大片 | 国产 精品 自在自线 | 国产午夜福利亚洲第一 | 美女极度色诱视频国产 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 亚洲男人av香蕉爽爽爽爽 | 日本大乳高潮视频在线观看 | 天天拍夜夜添久久精品 | 色情久久久av熟女人妻网站 | 少妇激情av一区二区 | 久久无码专区国产精品s | 亚洲 高清 成人 动漫 | 在线看片无码永久免费视频 | 亚洲精品一区二区三区婷婷月 | 天堂亚洲免费视频 | 久久亚洲中文字幕无码 | 国产另类ts人妖一区二区 | 最新国产乱人伦偷精品免费网站 | 亚洲s色大片在线观看 | 亚洲精品一区二区三区在线 | 日韩av无码一区二区三区 | 沈阳熟女露脸对白视频 | 台湾无码一区二区 | 一本一道久久综合久久 | 99国产精品白浆在线观看免费 | 精品无码国产自产拍在线观看蜜 | 国产人成高清在线视频99最全资源 | 亚洲码国产精品高潮在线 | 99久久精品无码一区二区毛片 | 国产亚洲精品久久久久久久 | 欧洲极品少妇 | 人人妻人人澡人人爽欧美一区 | 妺妺窝人体色www在线小说 | √天堂中文官网8在线 | 国产又粗又硬又大爽黄老大爷视 | 波多野结衣aⅴ在线 | 东京热无码av男人的天堂 | 欧美喷潮久久久xxxxx | 黑人玩弄人妻中文在线 | 内射巨臀欧美在线视频 | www国产精品内射老师 | 亚洲色欲色欲天天天www | 精品国偷自产在线视频 | 亚洲色大成网站www国产 | 老子影院午夜精品无码 | 精品乱码久久久久久久 | 一本久道久久综合婷婷五月 | 亚洲精品久久久久久久久久久 | 丰满人妻翻云覆雨呻吟视频 | 亚洲大尺度无码无码专区 | 丰满妇女强制高潮18xxxx | 在线播放亚洲第一字幕 | 亚洲色大成网站www | 丰满护士巨好爽好大乳 | 国产后入清纯学生妹 | 激情内射亚州一区二区三区爱妻 | 无码乱肉视频免费大全合集 | 人妻少妇精品视频专区 | 久久久无码中文字幕久... | 国产成人无码a区在线观看视频app | av无码不卡在线观看免费 | 激情人妻另类人妻伦 | 国产成人精品久久亚洲高清不卡 | 娇妻被黑人粗大高潮白浆 | 国产熟女一区二区三区四区五区 | 欧美成人午夜精品久久久 | 丰满少妇人妻久久久久久 | 九九久久精品国产免费看小说 | 18禁止看的免费污网站 | 亚洲国精产品一二二线 | 久久综合给合久久狠狠狠97色 | 久久久无码中文字幕久... | 欧美兽交xxxx×视频 | 久久视频在线观看精品 | 亚洲精品成人福利网站 | 国产亚洲精品久久久闺蜜 | 女人被爽到呻吟gif动态图视看 | 日韩人妻系列无码专区 | 成人性做爰aaa片免费看 | 国产av无码专区亚洲awww | 亚欧洲精品在线视频免费观看 | 国产欧美精品一区二区三区 | 国内精品一区二区三区不卡 | 国产精品久久久久久亚洲影视内衣 | 亲嘴扒胸摸屁股激烈网站 | 欧美野外疯狂做受xxxx高潮 | 2020久久香蕉国产线看观看 | 精品人人妻人人澡人人爽人人 | 久久这里只有精品视频9 | 日韩精品一区二区av在线 | 一本久道高清无码视频 | 中文字幕乱码人妻无码久久 | 国产真人无遮挡作爱免费视频 | 久久精品中文字幕大胸 | 亚洲精品久久久久久一区二区 | 西西人体www44rt大胆高清 | 无码av中文字幕免费放 | 成 人 免费观看网站 | 欧美精品国产综合久久 | 欧美日韩在线亚洲综合国产人 | 99re在线播放 | 成人免费视频视频在线观看 免费 | 亚洲国产精品久久久天堂 | 久久综合狠狠综合久久综合88 | 国产suv精品一区二区五 | 久久99精品久久久久婷婷 | 97精品人妻一区二区三区香蕉 | 久久久久人妻一区精品色欧美 | 久久午夜夜伦鲁鲁片无码免费 | 亚洲欧洲日本无在线码 | 国产精品久久久午夜夜伦鲁鲁 | 国产精品久久久久影院嫩草 | 国产精品va在线播放 | 国产精品美女久久久网av | 美女黄网站人色视频免费国产 | 亚洲国精产品一二二线 | 狠狠色噜噜狠狠狠7777奇米 | 天天做天天爱天天爽综合网 | 国产午夜福利亚洲第一 | 亚洲中文字幕乱码av波多ji | 国产精品久久国产三级国 | 少妇性荡欲午夜性开放视频剧场 | 亚洲精品中文字幕 | 国产莉萝无码av在线播放 | 国产人妻精品一区二区三区不卡 | 欧美激情内射喷水高潮 | 日韩人妻无码中文字幕视频 | 久久亚洲中文字幕精品一区 | 狂野欧美激情性xxxx | 欧美放荡的少妇 | 亚洲日韩av片在线观看 | 一本久道高清无码视频 | 久久人人97超碰a片精品 | 亚洲欧美日韩综合久久久 | 中文字幕av伊人av无码av | 精品人妻中文字幕有码在线 | 99久久亚洲精品无码毛片 | 亚洲乱码日产精品bd | 特黄特色大片免费播放器图片 | 久久99精品国产麻豆蜜芽 | 成人无码精品一区二区三区 | 丝袜人妻一区二区三区 | 男人扒开女人内裤强吻桶进去 | 美女扒开屁股让男人桶 | 少妇的肉体aa片免费 | 丰满少妇弄高潮了www | 亚洲乱码国产乱码精品精 | 性开放的女人aaa片 | 国产精品人人爽人人做我的可爱 | 欧美日韩色另类综合 | 又色又爽又黄的美女裸体网站 | 婷婷综合久久中文字幕蜜桃三电影 | 中文字幕无线码免费人妻 | 99久久久国产精品无码免费 | 成年美女黄网站色大免费全看 | 老熟女重囗味hdxx69 | 少妇太爽了在线观看 | 99久久人妻精品免费二区 | 131美女爱做视频 | 好男人www社区 | 欧美丰满熟妇xxxx | 国产av一区二区三区最新精品 | 亚洲中文字幕av在天堂 | 东京热无码av男人的天堂 | 亚洲中文字幕乱码av波多ji | 在线播放亚洲第一字幕 | 久久亚洲日韩精品一区二区三区 | 少妇人妻av毛片在线看 | 综合激情五月综合激情五月激情1 | 久久99精品久久久久久 | 巨爆乳无码视频在线观看 | 日本精品人妻无码77777 天堂一区人妻无码 | 性欧美牲交xxxxx视频 | 波多野42部无码喷潮在线 | 色婷婷欧美在线播放内射 | 永久免费观看美女裸体的网站 | 亚洲欧美精品伊人久久 | 亚洲色偷偷男人的天堂 | 亚洲色无码一区二区三区 | 亚洲精品久久久久中文第一幕 | 色 综合 欧美 亚洲 国产 | 亚洲国产精品无码一区二区三区 | 四虎永久在线精品免费网址 | 亚洲a无码综合a国产av中文 | 国产亚洲精品久久久久久国模美 | 国产人妻人伦精品 | 欧美精品一区二区精品久久 | 久久99精品国产麻豆蜜芽 | 无码福利日韩神码福利片 | 亚洲精品一区二区三区在线 | 东京热无码av男人的天堂 | 好男人www社区 | 欧美日韩在线亚洲综合国产人 | 中文字幕日产无线码一区 | 成人三级无码视频在线观看 | 玩弄少妇高潮ⅹxxxyw | 国产无套粉嫩白浆在线 | 高中生自慰www网站 | 男女性色大片免费网站 | 欧美猛少妇色xxxxx | 午夜精品久久久内射近拍高清 | 亚洲中文字幕va福利 | 亚洲理论电影在线观看 | 日本www一道久久久免费榴莲 | 婷婷综合久久中文字幕蜜桃三电影 | 精品欧美一区二区三区久久久 | 97久久精品无码一区二区 | 精品久久久久久人妻无码中文字幕 | 天堂а√在线地址中文在线 | 毛片内射-百度 | 精品久久久中文字幕人妻 | 综合网日日天干夜夜久久 | 又紧又大又爽精品一区二区 | 亚洲熟妇色xxxxx欧美老妇y | 久久综合给合久久狠狠狠97色 | 九一九色国产 | 伊人久久大香线蕉亚洲 | 午夜丰满少妇性开放视频 | 成熟妇人a片免费看网站 | 麻豆国产97在线 | 欧洲 | 中文字幕无码乱人伦 | 国产成人精品三级麻豆 | 久久精品99久久香蕉国产色戒 | 最近免费中文字幕中文高清百度 | 亚洲色欲色欲欲www在线 | 免费网站看v片在线18禁无码 | 亚洲自偷精品视频自拍 | 水蜜桃亚洲一二三四在线 | 色一情一乱一伦 | 熟妇人妻中文av无码 | 熟妇人妻无码xxx视频 | 成人欧美一区二区三区黑人免费 | 亚洲啪av永久无码精品放毛片 | 无码国产激情在线观看 | 成人精品视频一区二区 | 人妻有码中文字幕在线 | 国产特级毛片aaaaaa高潮流水 | 国产精品久久久久无码av色戒 | 中文字幕久久久久人妻 | 人妻有码中文字幕在线 | 国产人妻人伦精品1国产丝袜 | 亚洲 高清 成人 动漫 | 婷婷丁香五月天综合东京热 | 2019午夜福利不卡片在线 | 日本精品人妻无码免费大全 | 欧美猛少妇色xxxxx | 日韩在线不卡免费视频一区 | 性做久久久久久久免费看 | 中文字幕无码热在线视频 | 亚洲日韩av片在线观看 | 国产精品爱久久久久久久 | 人人妻人人澡人人爽精品欧美 | 在线成人www免费观看视频 | 天海翼激烈高潮到腰振不止 | 成人片黄网站色大片免费观看 | 人妻中文无码久热丝袜 | 亚洲乱码中文字幕在线 | 成人女人看片免费视频放人 | 婷婷综合久久中文字幕蜜桃三电影 | 高潮喷水的毛片 | 伊在人天堂亚洲香蕉精品区 | 精品国产青草久久久久福利 | 无码人妻出轨黑人中文字幕 | 久久综合狠狠综合久久综合88 | 疯狂三人交性欧美 | 午夜福利一区二区三区在线观看 | 中文无码成人免费视频在线观看 | 欧美 丝袜 自拍 制服 另类 | 中文毛片无遮挡高清免费 | 日日摸夜夜摸狠狠摸婷婷 | 国产偷自视频区视频 | 国产成人综合在线女婷五月99播放 | 在线观看国产一区二区三区 | 97夜夜澡人人爽人人喊中国片 | 欧美日本精品一区二区三区 | 内射欧美老妇wbb | 又黄又爽又色的视频 | 少妇久久久久久人妻无码 | 99久久精品日本一区二区免费 | 中文字幕无线码免费人妻 | 欧美人妻一区二区三区 | 色综合久久中文娱乐网 | av小次郎收藏 | 荫蒂添的好舒服视频囗交 | 中文字幕久久久久人妻 | 综合激情五月综合激情五月激情1 | 午夜精品久久久久久久 | 日产精品高潮呻吟av久久 | 丰满妇女强制高潮18xxxx | 久久国语露脸国产精品电影 | 大色综合色综合网站 | 成人精品视频一区二区三区尤物 | 中国女人内谢69xxxxxa片 | 国产综合久久久久鬼色 | 久久久婷婷五月亚洲97号色 | 国产香蕉尹人综合在线观看 | 久久无码人妻影院 | 亚洲精品久久久久中文第一幕 | 国产成人综合美国十次 | 性欧美疯狂xxxxbbbb | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 久久无码中文字幕免费影院蜜桃 | 在线观看欧美一区二区三区 | 亚洲国产午夜精品理论片 | 国产成人一区二区三区在线观看 | 又大又硬又黄的免费视频 | 国产乱人伦av在线无码 | 男人扒开女人内裤强吻桶进去 | 牲交欧美兽交欧美 | 两性色午夜免费视频 | 国产成人无码av一区二区 | 少妇性俱乐部纵欲狂欢电影 | 国产精品久久久午夜夜伦鲁鲁 | 天堂久久天堂av色综合 | 亚洲自偷精品视频自拍 | 久久综合激激的五月天 | 狠狠色色综合网站 | 成在人线av无码免观看麻豆 | 少妇厨房愉情理9仑片视频 | 亚洲欧洲日本无在线码 | 日本成熟视频免费视频 | 免费观看的无遮挡av | 美女极度色诱视频国产 | 久久国产精品偷任你爽任你 | 久精品国产欧美亚洲色aⅴ大片 | 无遮挡国产高潮视频免费观看 | 久久精品女人的天堂av | 久久熟妇人妻午夜寂寞影院 | 精品久久久久久亚洲精品 | 黑人粗大猛烈进出高潮视频 | 精品久久久久香蕉网 | 麻豆国产人妻欲求不满谁演的 | 四虎影视成人永久免费观看视频 | 99精品视频在线观看免费 | 国产乱人伦av在线无码 | 中文字幕av伊人av无码av | 性欧美videos高清精品 | 色情久久久av熟女人妻网站 | 久久久中文久久久无码 | 国产真实乱对白精彩久久 | 2020久久香蕉国产线看观看 | 国产超碰人人爽人人做人人添 | 在线精品亚洲一区二区 | 精品国产成人一区二区三区 | 精品成在人线av无码免费看 | 精品无码成人片一区二区98 | 久久午夜无码鲁丝片秋霞 | 久久午夜夜伦鲁鲁片无码免费 | 性生交片免费无码看人 | 日日夜夜撸啊撸 | 精品国产一区二区三区四区在线看 | 女人色极品影院 | 亚洲va欧美va天堂v国产综合 | 欧美精品在线观看 | 99麻豆久久久国产精品免费 | 人妻熟女一区 | 国产偷抇久久精品a片69 | 色噜噜亚洲男人的天堂 | 丰满人妻一区二区三区免费视频 | 又粗又大又硬毛片免费看 | 欧美人与善在线com | 国产成人一区二区三区别 | 亚洲gv猛男gv无码男同 | 在线亚洲高清揄拍自拍一品区 | 亚洲精品成人av在线 | 超碰97人人射妻 | 午夜福利一区二区三区在线观看 | 人妻尝试又大又粗久久 | 国产人妻精品午夜福利免费 | 日日干夜夜干 | 亚洲色成人中文字幕网站 | 亚欧洲精品在线视频免费观看 | 国产成人无码专区 | 国产精品沙发午睡系列 | 麻豆精产国品 | 日本va欧美va欧美va精品 | 久久久久久久人妻无码中文字幕爆 | 女人被爽到呻吟gif动态图视看 | 久久人人爽人人爽人人片ⅴ | 日本爽爽爽爽爽爽在线观看免 | 久久午夜无码鲁丝片午夜精品 | 久久久久久久久888 | 免费人成在线观看网站 | 久久久精品欧美一区二区免费 | 亚洲а∨天堂久久精品2021 | 亚洲人成人无码网www国产 | 麻花豆传媒剧国产免费mv在线 | 久久精品国产99久久6动漫 | 久久精品丝袜高跟鞋 | 影音先锋中文字幕无码 | 久久久久久国产精品无码下载 | 国产免费无码一区二区视频 | 成 人 网 站国产免费观看 | 亚洲一区二区观看播放 | 亚洲精品成人福利网站 | 日本爽爽爽爽爽爽在线观看免 | 亚洲gv猛男gv无码男同 | 久久精品国产精品国产精品污 | 乱人伦人妻中文字幕无码久久网 | 精品久久久无码人妻字幂 | 亚洲日韩一区二区三区 | 男女作爱免费网站 | 久精品国产欧美亚洲色aⅴ大片 | 久久亚洲日韩精品一区二区三区 | 色老头在线一区二区三区 | 人妻少妇精品无码专区二区 | 国产精品无码永久免费888 | 精品一区二区三区波多野结衣 | 亚洲精品国产a久久久久久 | 成人亚洲精品久久久久软件 | 久久久久久久人妻无码中文字幕爆 | 亚洲中文字幕无码一久久区 | 99久久精品国产一区二区蜜芽 | 日韩亚洲欧美精品综合 | 免费无码午夜福利片69 | 久9re热视频这里只有精品 | 狠狠躁日日躁夜夜躁2020 | 国产成人综合在线女婷五月99播放 | 国产亚洲精品久久久久久大师 | 亚洲人成影院在线无码按摩店 | 国产成人精品久久亚洲高清不卡 | 无码福利日韩神码福利片 | 狠狠色噜噜狠狠狠狠7777米奇 | 激情爆乳一区二区三区 | 国产精品毛片一区二区 | 亚洲人成无码网www | 亚洲国产精品毛片av不卡在线 | 久久综合狠狠综合久久综合88 | 99精品视频在线观看免费 | 一本久久a久久精品亚洲 | 大胆欧美熟妇xx | 国产偷抇久久精品a片69 | 成人无码精品1区2区3区免费看 | 国精品人妻无码一区二区三区蜜柚 | 亚洲午夜无码久久 | 无码播放一区二区三区 | 久久精品人人做人人综合试看 | 国产真实乱对白精彩久久 | 欧美日韩在线亚洲综合国产人 | 亚洲一区av无码专区在线观看 | 中文字幕中文有码在线 | 999久久久国产精品消防器材 | 精品国产青草久久久久福利 | 成人欧美一区二区三区黑人免费 | 图片小说视频一区二区 | 国产亚洲精品久久久久久国模美 | 国内精品人妻无码久久久影院蜜桃 | 国产 浪潮av性色四虎 | √天堂资源地址中文在线 | 沈阳熟女露脸对白视频 | 特黄特色大片免费播放器图片 | 无码任你躁久久久久久久 | a在线亚洲男人的天堂 | 国产成人一区二区三区在线观看 | 国产超级va在线观看视频 | 欧美成人免费全部网站 | 激情内射日本一区二区三区 | 国产成人午夜福利在线播放 | 精品国产福利一区二区 | 国精产品一品二品国精品69xx | 在线а√天堂中文官网 | 亚洲日韩中文字幕在线播放 | 少妇人妻大乳在线视频 | 欧美亚洲日韩国产人成在线播放 | 女人被男人躁得好爽免费视频 | 欧美午夜特黄aaaaaa片 | 国产精品久久国产精品99 | av人摸人人人澡人人超碰下载 | 亚洲人成无码网www | 国产成人久久精品流白浆 | 亚洲经典千人经典日产 | 亚洲人亚洲人成电影网站色 | 亚洲大尺度无码无码专区 | 日产国产精品亚洲系列 | 97夜夜澡人人爽人人喊中国片 | 午夜不卡av免费 一本久久a久久精品vr综合 | 免费人成在线视频无码 | 男女猛烈xx00免费视频试看 | 中国女人内谢69xxxxxa片 | 伊人色综合久久天天小片 | 初尝人妻少妇中文字幕 | 国产特级毛片aaaaaaa高清 | 国产精品沙发午睡系列 | 国产高清不卡无码视频 | а√天堂www在线天堂小说 | 欧美日韩在线亚洲综合国产人 | 西西人体www44rt大胆高清 | 精品国产乱码久久久久乱码 | 国产亚洲精品久久久久久久久动漫 | 亚洲精品综合一区二区三区在线 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 国内精品人妻无码久久久影院蜜桃 | 欧美第一黄网免费网站 | 97无码免费人妻超级碰碰夜夜 | 日韩亚洲欧美精品综合 | 亚洲人成无码网www | 无码午夜成人1000部免费视频 | 精品人人妻人人澡人人爽人人 | 精品欧洲av无码一区二区三区 | 牛和人交xxxx欧美 | 久久久精品国产sm最大网站 | 日本一区二区三区免费高清 | 欧美成人高清在线播放 | 中文无码成人免费视频在线观看 | 色婷婷av一区二区三区之红樱桃 | 四虎国产精品一区二区 | 永久免费精品精品永久-夜色 | 欧美日韩久久久精品a片 | www一区二区www免费 | 图片小说视频一区二区 | 我要看www免费看插插视频 | 乱人伦中文视频在线观看 | 久久久精品成人免费观看 | 欧美 亚洲 国产 另类 | 午夜不卡av免费 一本久久a久久精品vr综合 | 亚洲乱亚洲乱妇50p | 女人被爽到呻吟gif动态图视看 | 蜜桃视频插满18在线观看 | 帮老师解开蕾丝奶罩吸乳网站 | 日韩精品无码免费一区二区三区 | 欧美freesex黑人又粗又大 | 国产精品久久久久影院嫩草 | 国产精品亚洲综合色区韩国 | 精品人妻人人做人人爽夜夜爽 | 国产精品毛片一区二区 | 乱人伦中文视频在线观看 | 国内精品人妻无码久久久影院 | 中文精品无码中文字幕无码专区 | 久久久久成人精品免费播放动漫 | 久久精品国产日本波多野结衣 | 300部国产真实乱 | 国产精品爱久久久久久久 | 亚洲爆乳无码专区 | 男人的天堂av网站 | 免费观看又污又黄的网站 | 亚洲精品中文字幕久久久久 | 亚洲精品成a人在线观看 | 最新国产乱人伦偷精品免费网站 | 亚洲日本一区二区三区在线 | 久久久久成人片免费观看蜜芽 | 男女性色大片免费网站 | 国产xxx69麻豆国语对白 | 久久zyz资源站无码中文动漫 | 性欧美疯狂xxxxbbbb | 熟妇女人妻丰满少妇中文字幕 | 特黄特色大片免费播放器图片 | 奇米影视888欧美在线观看 | 欧美一区二区三区视频在线观看 | 久久精品中文字幕一区 | 亚洲一区av无码专区在线观看 | 无码乱肉视频免费大全合集 | 在线精品国产一区二区三区 | 性色av无码免费一区二区三区 | 无套内射视频囯产 | 好爽又高潮了毛片免费下载 | 水蜜桃亚洲一二三四在线 | 亚洲精品国偷拍自产在线观看蜜桃 | 中文字幕无码热在线视频 | 免费人成在线观看网站 | 久久久久久av无码免费看大片 | 国产成人无码av一区二区 | 欧美自拍另类欧美综合图片区 | 在线播放亚洲第一字幕 | 午夜精品久久久久久久久 | 久久精品国产日本波多野结衣 | 日本护士毛茸茸高潮 | 丰满肥臀大屁股熟妇激情视频 | 中文精品无码中文字幕无码专区 | 国产农村妇女高潮大叫 | 无码精品国产va在线观看dvd | 十八禁视频网站在线观看 | 高清国产亚洲精品自在久久 | 欧美性黑人极品hd | 亚洲中文字幕在线观看 | 免费无码一区二区三区蜜桃大 | 成年美女黄网站色大免费全看 | 天天做天天爱天天爽综合网 | 奇米影视888欧美在线观看 | 乱码午夜-极国产极内射 | 中文字幕无线码免费人妻 | 少妇性l交大片 | 精品国产福利一区二区 | 正在播放东北夫妻内射 | 一二三四在线观看免费视频 | 亚洲精品一区国产 | 国产福利视频一区二区 | 国产亚洲精品久久久久久久久动漫 | 欧美老妇与禽交 | 67194成是人免费无码 | 在线播放亚洲第一字幕 | yw尤物av无码国产在线观看 | 国产亲子乱弄免费视频 | 97精品国产97久久久久久免费 | 亚洲色偷偷男人的天堂 | 久久国语露脸国产精品电影 | 国产精品毛多多水多 | 欧美熟妇另类久久久久久多毛 | 午夜无码人妻av大片色欲 | 天天燥日日燥 | 亚洲一区二区三区无码久久 | 夜夜影院未满十八勿进 | 高潮毛片无遮挡高清免费 | 中文亚洲成a人片在线观看 | 国产午夜视频在线观看 | 国产特级毛片aaaaaa高潮流水 | 2020最新国产自产精品 | 久久99久久99精品中文字幕 | 99er热精品视频 | 精品乱码久久久久久久 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 大乳丰满人妻中文字幕日本 | 欧美日韩一区二区三区自拍 | 亚洲国产精品久久久久久 | 少妇无码一区二区二三区 | 中文字幕 人妻熟女 | 国产成人一区二区三区别 | 扒开双腿疯狂进出爽爽爽视频 | 亚洲午夜无码久久 | 日欧一片内射va在线影院 | 男女下面进入的视频免费午夜 | 偷窥日本少妇撒尿chinese | 欧美一区二区三区视频在线观看 | 欧美成人高清在线播放 | 俺去俺来也在线www色官网 | 免费乱码人妻系列无码专区 | 日韩精品成人一区二区三区 | 一本大道伊人av久久综合 | 欧美人与禽猛交狂配 | 国产精品久免费的黄网站 | 国产精品资源一区二区 | 三上悠亚人妻中文字幕在线 | www国产亚洲精品久久网站 | 特级做a爰片毛片免费69 | 女人和拘做爰正片视频 | 欧美喷潮久久久xxxxx | 内射巨臀欧美在线视频 | 亚洲国产一区二区三区在线观看 | 88国产精品欧美一区二区三区 | 日韩欧美中文字幕公布 | 99久久精品午夜一区二区 | 欧美人与善在线com | 乱人伦中文视频在线观看 | 奇米影视7777久久精品 | 亚洲色在线无码国产精品不卡 | 啦啦啦www在线观看免费视频 | 欧美自拍另类欧美综合图片区 | 熟妇女人妻丰满少妇中文字幕 | 午夜精品一区二区三区在线观看 | 久久亚洲国产成人精品性色 | 亚洲精品一区二区三区大桥未久 | 色欲人妻aaaaaaa无码 | 国精产品一区二区三区 | 日韩精品一区二区av在线 | 中文无码伦av中文字幕 | 无码人妻出轨黑人中文字幕 | 欧洲熟妇色 欧美 | 国产乱人伦av在线无码 | 国产精品人妻一区二区三区四 | 久久亚洲日韩精品一区二区三区 | 国产精品无码成人午夜电影 | 成人动漫在线观看 | 天天躁日日躁狠狠躁免费麻豆 | 亚洲天堂2017无码中文 | 久久久av男人的天堂 | 国产九九九九九九九a片 | 欧美猛少妇色xxxxx | 婷婷色婷婷开心五月四房播播 | 野狼第一精品社区 | 日韩精品a片一区二区三区妖精 | 免费观看激色视频网站 | 国产精品二区一区二区aⅴ污介绍 | 日本一卡二卡不卡视频查询 | 内射老妇bbwx0c0ck | 国产亚av手机在线观看 | 国产成人精品视频ⅴa片软件竹菊 | 又粗又大又硬又长又爽 | 欧美国产亚洲日韩在线二区 | 久久国产精品_国产精品 | 亚洲精品国产精品乱码视色 | 色妞www精品免费视频 | 国产精品国产三级国产专播 | 国产亚洲人成a在线v网站 | 中文字幕+乱码+中文字幕一区 | 国产三级久久久精品麻豆三级 | 中文字幕乱码人妻无码久久 | 99久久无码一区人妻 | 国内精品人妻无码久久久影院 | 性生交大片免费看女人按摩摩 | 日韩av无码一区二区三区不卡 | 亚洲欧美国产精品专区久久 | 亚洲中文字幕在线观看 | 亚洲日韩av片在线观看 | www国产亚洲精品久久网站 | 鲁一鲁av2019在线 | 天天躁夜夜躁狠狠是什么心态 | 荡女精品导航 | 蜜桃臀无码内射一区二区三区 | 婷婷五月综合激情中文字幕 | 欧美性生交活xxxxxdddd | 精品国产av色一区二区深夜久久 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 国产精品va在线播放 | 精品夜夜澡人妻无码av蜜桃 | 日本免费一区二区三区最新 | 老熟妇仑乱视频一区二区 | 丰满人妻一区二区三区免费视频 | 中国女人内谢69xxxxxa片 | 国产精品国产自线拍免费软件 | 又紧又大又爽精品一区二区 | 国产精品第一国产精品 | 免费乱码人妻系列无码专区 | 亲嘴扒胸摸屁股激烈网站 | 亚洲熟妇色xxxxx亚洲 | 男女猛烈xx00免费视频试看 | 2020久久超碰国产精品最新 | 久久无码专区国产精品s | 亚洲成熟女人毛毛耸耸多 | 国产成人无码av在线影院 | 四虎4hu永久免费 | 亚洲一区av无码专区在线观看 | 亚洲熟妇色xxxxx亚洲 | 人人爽人人澡人人高潮 | 中文精品久久久久人妻不卡 | 草草网站影院白丝内射 | 亚洲国产午夜精品理论片 | 日日摸夜夜摸狠狠摸婷婷 | 国产激情艳情在线看视频 | 在教室伦流澡到高潮hnp视频 | 国产亚洲精品久久久久久久久动漫 | 国产成人人人97超碰超爽8 | 国产一区二区三区影院 | 亚洲娇小与黑人巨大交 | 狠狠cao日日穞夜夜穞av | 无码成人精品区在线观看 | 乌克兰少妇xxxx做受 | 少妇性l交大片欧洲热妇乱xxx | 自拍偷自拍亚洲精品被多人伦好爽 | 日本www一道久久久免费榴莲 | 日本乱人伦片中文三区 | 国产av人人夜夜澡人人爽麻豆 | 国内揄拍国内精品人妻 | 免费中文字幕日韩欧美 | 东北女人啪啪对白 | 玩弄中年熟妇正在播放 | 亚洲精品国产精品乱码不卡 | 丁香花在线影院观看在线播放 | 日韩av无码一区二区三区 | 中文字幕av无码一区二区三区电影 | 中文毛片无遮挡高清免费 | 激情综合激情五月俺也去 | 欧美性生交活xxxxxdddd | 久久人人爽人人爽人人片ⅴ | 日本大乳高潮视频在线观看 | 一本加勒比波多野结衣 | 午夜理论片yy44880影院 | 在线播放免费人成毛片乱码 | 日韩 欧美 动漫 国产 制服 | 久久精品一区二区三区四区 | 久久久精品成人免费观看 | 中文字幕人妻无码一夲道 | 好爽又高潮了毛片免费下载 | ass日本丰满熟妇pics | 国产激情综合五月久久 | 国产97人人超碰caoprom | 88国产精品欧美一区二区三区 | 美女毛片一区二区三区四区 | 中文字幕无码av波多野吉衣 | 国内老熟妇对白xxxxhd | 国产人妻人伦精品1国产丝袜 | 日本乱偷人妻中文字幕 | 图片小说视频一区二区 | 激情内射日本一区二区三区 | 国产午夜福利100集发布 | 欧美成人家庭影院 | 国产特级毛片aaaaaa高潮流水 | 四十如虎的丰满熟妇啪啪 | 国产一区二区不卡老阿姨 | 亚洲熟女一区二区三区 | 日本精品久久久久中文字幕 | 亚洲精品国产精品乱码视色 | 女人被爽到呻吟gif动态图视看 | 国产人妻人伦精品 | 国产精品永久免费视频 | 中文字幕无码人妻少妇免费 | 天堂а√在线中文在线 | 国产免费无码一区二区视频 | 99精品无人区乱码1区2区3区 | 日韩欧美中文字幕公布 | 草草网站影院白丝内射 | 人人超人人超碰超国产 | 精品一区二区三区无码免费视频 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 久久成人a毛片免费观看网站 | 亚洲午夜久久久影院 | 色婷婷综合激情综在线播放 | 三上悠亚人妻中文字幕在线 | 色诱久久久久综合网ywww | 国产精品多人p群无码 | 无套内谢老熟女 | 亚洲阿v天堂在线 | 牲欲强的熟妇农村老妇女 | 亚洲熟妇色xxxxx欧美老妇y | 在线成人www免费观看视频 | 少妇无套内谢久久久久 | 伊人久久婷婷五月综合97色 | 欧美精品无码一区二区三区 | 爆乳一区二区三区无码 | 亚洲一区二区三区国产精华液 | 国产色在线 | 国产 | 免费观看又污又黄的网站 | 国产精品a成v人在线播放 | 国产在线精品一区二区三区直播 | 无码吃奶揉捏奶头高潮视频 | 精品一二三区久久aaa片 | 性做久久久久久久免费看 | 四虎影视成人永久免费观看视频 | 丰满少妇弄高潮了www | 人人妻人人澡人人爽欧美一区九九 | 丰满少妇弄高潮了www | 亚洲欧洲中文日韩av乱码 | 久久精品国产一区二区三区 | 国产成人精品久久亚洲高清不卡 | 久久亚洲国产成人精品性色 | 扒开双腿疯狂进出爽爽爽视频 | 乱人伦人妻中文字幕无码久久网 | 国产欧美熟妇另类久久久 | 欧美亚洲日韩国产人成在线播放 | 国产精品美女久久久网av | 国产 精品 自在自线 | 在线天堂新版最新版在线8 | 人妻插b视频一区二区三区 | 88国产精品欧美一区二区三区 | 日韩精品无码一本二本三本色 | 国产成人午夜福利在线播放 | 久久久久久九九精品久 | 久久久精品欧美一区二区免费 | 欧美老妇与禽交 | 国产一区二区三区精品视频 | 欧美国产日韩亚洲中文 | 欧美熟妇另类久久久久久不卡 | 国产亲子乱弄免费视频 | 97资源共享在线视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 成年美女黄网站色大免费视频 | 国产成人无码a区在线观看视频app | 国产亚洲欧美日韩亚洲中文色 | 男女性色大片免费网站 | 国产亚洲精品精品国产亚洲综合 | 久久www免费人成人片 | 色偷偷人人澡人人爽人人模 | 欧美日韩综合一区二区三区 | 无遮挡啪啪摇乳动态图 | 国产欧美精品一区二区三区 | 九九热爱视频精品 | 小泽玛莉亚一区二区视频在线 | 欧美人与物videos另类 | √天堂中文官网8在线 | 亚洲人成影院在线无码按摩店 | 久久精品国产亚洲精品 | 久久无码人妻影院 | 国产综合色产在线精品 | 色一情一乱一伦一区二区三欧美 | 国产福利视频一区二区 | 老熟妇乱子伦牲交视频 | 两性色午夜视频免费播放 | 曰韩无码二三区中文字幕 | 亚洲国产欧美日韩精品一区二区三区 | 免费看少妇作爱视频 | 永久免费观看美女裸体的网站 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲区小说区激情区图片区 | 亚洲国产精品成人久久蜜臀 | 又紧又大又爽精品一区二区 | 兔费看少妇性l交大片免费 | 亚洲爆乳大丰满无码专区 | 无码一区二区三区在线观看 | 国产精品亚洲а∨无码播放麻豆 | 一二三四在线观看免费视频 | 无码人妻少妇伦在线电影 | 5858s亚洲色大成网站www | 少妇的肉体aa片免费 | 无码精品人妻一区二区三区av | 天堂无码人妻精品一区二区三区 | 国产精品亚洲lv粉色 | 国产精品久久久久7777 | 国产乱码精品一品二品 | 中文无码伦av中文字幕 | 欧美兽交xxxx×视频 | 精品水蜜桃久久久久久久 | 精品人妻人人做人人爽 | 午夜福利一区二区三区在线观看 | 在线а√天堂中文官网 | 日韩精品久久久肉伦网站 | 久久久婷婷五月亚洲97号色 | www成人国产高清内射 | 国产黑色丝袜在线播放 | 欧美成人午夜精品久久久 | 无码国产乱人伦偷精品视频 | 熟妇人妻激情偷爽文 | 亚洲中文字幕无码一久久区 | 三上悠亚人妻中文字幕在线 | 国产人妻精品一区二区三区不卡 | 亚洲日韩av片在线观看 | 色一情一乱一伦一区二区三欧美 | 久久精品国产日本波多野结衣 | 色欲av亚洲一区无码少妇 | 欧美日韩综合一区二区三区 | 国产超级va在线观看视频 | 四虎永久在线精品免费网址 | 免费看男女做好爽好硬视频 | 国产精品久久福利网站 | 欧美阿v高清资源不卡在线播放 | 欧美日韩在线亚洲综合国产人 | 无码人妻丰满熟妇区毛片18 | 中文字幕无码av波多野吉衣 | 国产精品亚洲一区二区三区喷水 | 亚洲中文字幕在线观看 | 久久精品国产99久久6动漫 | 精品无人国产偷自产在线 | 精品无人国产偷自产在线 | 一二三四社区在线中文视频 | 亚洲の无码国产の无码影院 | 麻豆成人精品国产免费 | 国产精品成人av在线观看 | 四十如虎的丰满熟妇啪啪 | 男女性色大片免费网站 | 综合人妻久久一区二区精品 | 久久久久免费看成人影片 | 亚洲va中文字幕无码久久不卡 | 日韩av无码一区二区三区 | 久久aⅴ免费观看 | 久久精品国产日本波多野结衣 | 捆绑白丝粉色jk震动捧喷白浆 | 国产舌乚八伦偷品w中 | 久久久久人妻一区精品色欧美 | 人人妻人人澡人人爽欧美一区九九 | а天堂中文在线官网 | 亚洲一区二区三区含羞草 | 一个人看的视频www在线 | 精品国产麻豆免费人成网站 | 男人扒开女人内裤强吻桶进去 | 亚洲色无码一区二区三区 | 一本久久a久久精品亚洲 | 鲁一鲁av2019在线 | 荫蒂被男人添的好舒服爽免费视频 | 亚洲精品国偷拍自产在线麻豆 | 午夜无码区在线观看 | 亚洲精品午夜国产va久久成人 | 亚洲欧美精品aaaaaa片 | 国产成人精品无码播放 | 午夜精品久久久久久久 | 日本护士毛茸茸高潮 | 日欧一片内射va在线影院 | 亚洲第一网站男人都懂 | 狠狠噜狠狠狠狠丁香五月 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 99久久久无码国产aaa精品 | 免费乱码人妻系列无码专区 | 国产农村妇女高潮大叫 | 日产国产精品亚洲系列 | 天天拍夜夜添久久精品大 | 扒开双腿吃奶呻吟做受视频 | 午夜熟女插插xx免费视频 | 亚洲色偷偷偷综合网 | 中文字幕亚洲情99在线 | 精品人人妻人人澡人人爽人人 | 久青草影院在线观看国产 | 精品国产青草久久久久福利 | 男女爱爱好爽视频免费看 | 国产成人综合在线女婷五月99播放 | av在线亚洲欧洲日产一区二区 | 内射欧美老妇wbb | 中文字幕久久久久人妻 | 捆绑白丝粉色jk震动捧喷白浆 | 久久综合给久久狠狠97色 | 欧美三级a做爰在线观看 | 日本一区二区更新不卡 | 日韩精品无码免费一区二区三区 | 国产av久久久久精东av | 国产网红无码精品视频 | 欧美老熟妇乱xxxxx | 精品国产福利一区二区 | 牲欲强的熟妇农村老妇女视频 | 国产精品久久国产三级国 | 国产成人精品无码播放 | 国产综合久久久久鬼色 | 亚洲人成影院在线无码按摩店 | 色综合久久网 | 娇妻被黑人粗大高潮白浆 | 性欧美大战久久久久久久 | 精品夜夜澡人妻无码av蜜桃 | 亚洲无人区午夜福利码高清完整版 | 天海翼激烈高潮到腰振不止 | 欧美老人巨大xxxx做受 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 国精产品一品二品国精品69xx | 亚洲一区二区三区在线观看网站 | 欧美成人免费全部网站 | 又黄又爽又色的视频 | 女人被男人躁得好爽免费视频 | 国精品人妻无码一区二区三区蜜柚 | 女人被男人爽到呻吟的视频 | 国产福利视频一区二区 | 在线播放免费人成毛片乱码 | 人妻天天爽夜夜爽一区二区 | 少妇被粗大的猛进出69影院 | 欧美老熟妇乱xxxxx | 玩弄中年熟妇正在播放 | 人人妻人人澡人人爽人人精品 | 亚洲一区二区三区国产精华液 | 久久亚洲中文字幕无码 | 亚洲国产av精品一区二区蜜芽 | 图片小说视频一区二区 | 免费网站看v片在线18禁无码 | 久久久久免费看成人影片 | 狠狠色欧美亚洲狠狠色www | www国产亚洲精品久久久日本 | 国产免费久久精品国产传媒 | 久久久久99精品成人片 | 成人精品一区二区三区中文字幕 | 四十如虎的丰满熟妇啪啪 | 日韩少妇白浆无码系列 | 国产精品亚洲五月天高清 | 国产精品无码一区二区桃花视频 | 欧美熟妇另类久久久久久多毛 | 国内精品九九久久久精品 | 欧美成人家庭影院 | 亚洲七七久久桃花影院 | 丰满少妇女裸体bbw | 300部国产真实乱 | 日本www一道久久久免费榴莲 | 亚洲 激情 小说 另类 欧美 | 一个人看的视频www在线 | 无码吃奶揉捏奶头高潮视频 | 国产成人无码av片在线观看不卡 | 精品国精品国产自在久国产87 | 亚洲 高清 成人 动漫 | 未满小14洗澡无码视频网站 | 精品偷自拍另类在线观看 | 人妻少妇精品无码专区二区 | 久久视频在线观看精品 | 精品一区二区三区无码免费视频 | 伊人久久婷婷五月综合97色 | 亚洲国产欧美日韩精品一区二区三区 | 荫蒂被男人添的好舒服爽免费视频 | 激情人妻另类人妻伦 | 伊人久久大香线蕉av一区二区 | 久久国产精品二国产精品 | 国产办公室秘书无码精品99 | 精品一区二区三区无码免费视频 | 久久久久成人片免费观看蜜芽 | 三上悠亚人妻中文字幕在线 | 在线播放免费人成毛片乱码 | 精品日本一区二区三区在线观看 | 九九在线中文字幕无码 | 国产激情艳情在线看视频 | 亚洲 a v无 码免 费 成 人 a v | 无码乱肉视频免费大全合集 | 色五月丁香五月综合五月 | 丁香花在线影院观看在线播放 | 色婷婷久久一区二区三区麻豆 | 亚洲自偷自偷在线制服 | 国产精品久久久久无码av色戒 | 台湾无码一区二区 | 未满小14洗澡无码视频网站 | 久久久久成人精品免费播放动漫 | 国产乱码精品一品二品 | 国产在线精品一区二区高清不卡 | 国产偷自视频区视频 | 国产香蕉97碰碰久久人人 | 国产又爽又黄又刺激的视频 | 亚洲一区二区三区四区 | 国产偷抇久久精品a片69 | 成年美女黄网站色大免费全看 | 一本久道久久综合狠狠爱 | 久久综合九色综合97网 | 国产激情精品一区二区三区 | 老熟妇乱子伦牲交视频 | 奇米影视888欧美在线观看 | 男人的天堂av网站 | 久久无码中文字幕免费影院蜜桃 | 东京无码熟妇人妻av在线网址 | 精品夜夜澡人妻无码av蜜桃 | 1000部啪啪未满十八勿入下载 | 国产精品久久久久久久影院 | 丰满人妻被黑人猛烈进入 | 波多野42部无码喷潮在线 | 亚洲男人av香蕉爽爽爽爽 | 丝袜 中出 制服 人妻 美腿 | 久久久久人妻一区精品色欧美 | 三级4级全黄60分钟 | 宝宝好涨水快流出来免费视频 | 天堂在线观看www | 色欲久久久天天天综合网精品 | 人妻与老人中文字幕 | 欧美老熟妇乱xxxxx | 丰满少妇熟乱xxxxx视频 | 国产亚洲欧美在线专区 | 国产成人久久精品流白浆 | 欧美日韩视频无码一区二区三 | 国产人妻人伦精品1国产丝袜 | 天天拍夜夜添久久精品 | 少妇无码av无码专区在线观看 | 在线精品亚洲一区二区 | 在线a亚洲视频播放在线观看 | 久久精品国产99精品亚洲 | 极品尤物被啪到呻吟喷水 | 国产激情无码一区二区app | 欧美三级a做爰在线观看 | 国产精品99爱免费视频 | 国产成人无码区免费内射一片色欲 | 国产乱子伦视频在线播放 | av在线亚洲欧洲日产一区二区 | 欧美日韩在线亚洲综合国产人 | 中文字幕乱码中文乱码51精品 | 欧美丰满老熟妇xxxxx性 | 人人妻人人澡人人爽欧美一区九九 | 国产精品久久精品三级 | 久久99精品国产麻豆 | 婷婷丁香五月天综合东京热 | 久久精品中文字幕大胸 | 久热国产vs视频在线观看 | 狠狠cao日日穞夜夜穞av | 性欧美熟妇videofreesex | 中国大陆精品视频xxxx | 2019nv天堂香蕉在线观看 | 日本丰满护士爆乳xxxx | 久久久久99精品国产片 | 内射巨臀欧美在线视频 | 欧美xxxx黑人又粗又长 | 人人妻人人澡人人爽人人精品 | 亚洲精品国产a久久久久久 | 真人与拘做受免费视频一 | 午夜性刺激在线视频免费 | 成人精品视频一区二区 | 成人免费视频一区二区 | 高潮毛片无遮挡高清免费视频 | 久久久久se色偷偷亚洲精品av | 蜜桃臀无码内射一区二区三区 | 国产精品无码成人午夜电影 | 国产成人精品视频ⅴa片软件竹菊 | av无码久久久久不卡免费网站 | 欧美丰满少妇xxxx性 | 国色天香社区在线视频 | 亚洲色偷偷偷综合网 | 无码av岛国片在线播放 | 久久久久久亚洲精品a片成人 | 中文无码精品a∨在线观看不卡 | 国产精品鲁鲁鲁 | 亚洲色www成人永久网址 | 亚洲精品午夜无码电影网 | 亚洲中文字幕va福利 | 国产av一区二区三区最新精品 | 国产午夜福利亚洲第一 | 国产一区二区三区精品视频 | 九九久久精品国产免费看小说 | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美 亚洲 国产 另类 | 国产国产精品人在线视 | 国产精品无码永久免费888 | 精品亚洲成av人在线观看 | 国产一精品一av一免费 | 成年美女黄网站色大免费全看 | 天天拍夜夜添久久精品大 | 丰满岳乱妇在线观看中字无码 | 国产精品久久久一区二区三区 | 国精品人妻无码一区二区三区蜜柚 | 久久久久99精品成人片 | √天堂中文官网8在线 | 欧美国产日韩亚洲中文 | 1000部啪啪未满十八勿入下载 | 欧美国产亚洲日韩在线二区 | 乌克兰少妇性做爰 | 国产av人人夜夜澡人人爽麻豆 | 国产精品亚洲а∨无码播放麻豆 | 国产精品久久久一区二区三区 | 欧美性黑人极品hd | 精品亚洲韩国一区二区三区 | 精品无码国产自产拍在线观看蜜 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 欧美精品在线观看 | a国产一区二区免费入口 | 少妇厨房愉情理9仑片视频 | 欧美熟妇另类久久久久久多毛 | 人人爽人人澡人人高潮 | 中文无码成人免费视频在线观看 | 亚洲精品www久久久 | 久久久精品国产sm最大网站 | 噜噜噜亚洲色成人网站 | 成熟妇人a片免费看网站 | 熟妇女人妻丰满少妇中文字幕 | 欧美真人作爱免费视频 | 少妇激情av一区二区 | 亚洲精品一区三区三区在线观看 | 理论片87福利理论电影 | 精品乱子伦一区二区三区 | 男人扒开女人内裤强吻桶进去 | 国产精品二区一区二区aⅴ污介绍 | 国产亚洲人成a在线v网站 | 日本精品少妇一区二区三区 | 国产婷婷色一区二区三区在线 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产亚洲精品久久久ai换 | 成人一区二区免费视频 | 中文字幕无码人妻少妇免费 | a在线亚洲男人的天堂 | 精品国产一区av天美传媒 | 久久久www成人免费毛片 | 日韩av无码一区二区三区不卡 | 亚洲成av人在线观看网址 | 成人片黄网站色大片免费观看 | 玩弄少妇高潮ⅹxxxyw | 欧美成人免费全部网站 | 亚洲爆乳精品无码一区二区三区 | 蜜桃视频插满18在线观看 | 中文字幕无码免费久久9一区9 | 国产成人综合美国十次 | 欧美猛少妇色xxxxx | 国产精品久久久午夜夜伦鲁鲁 | 中文字幕乱码亚洲无线三区 | 香蕉久久久久久av成人 | 国产精品高潮呻吟av久久 | 在线观看免费人成视频 | 无码一区二区三区在线观看 | 无码人妻精品一区二区三区不卡 | 亚洲人成影院在线观看 | 永久免费精品精品永久-夜色 | 亚洲成色在线综合网站 | 精品国产精品久久一区免费式 | 亚洲日本一区二区三区在线 | 国产9 9在线 | 中文 | 亚洲а∨天堂久久精品2021 | 亚洲成av人影院在线观看 | a在线观看免费网站大全 | 国产亚洲欧美日韩亚洲中文色 | 暴力强奷在线播放无码 | 精品亚洲成av人在线观看 | 国产精品国产自线拍免费软件 | 午夜丰满少妇性开放视频 | 国产激情一区二区三区 | 亚洲精品美女久久久久久久 | 色婷婷综合激情综在线播放 | 日本乱人伦片中文三区 | 日本va欧美va欧美va精品 | 一二三四在线观看免费视频 | 久久国产精品二国产精品 | 国产手机在线αⅴ片无码观看 | 7777奇米四色成人眼影 | 熟妇人妻激情偷爽文 | 99er热精品视频 | 激情国产av做激情国产爱 | 岛国片人妻三上悠亚 | 日日橹狠狠爱欧美视频 | 国产成人亚洲综合无码 | 99久久99久久免费精品蜜桃 | 中文精品久久久久人妻不卡 | 亚洲熟妇色xxxxx亚洲 | 蜜臀aⅴ国产精品久久久国产老师 | 欧美zoozzooz性欧美 | 无人区乱码一区二区三区 | 国产精品18久久久久久麻辣 | 一区二区三区高清视频一 | 成人一区二区免费视频 | 国产精品欧美成人 | 国产亚洲视频中文字幕97精品 | 少妇激情av一区二区 | 国产片av国语在线观看 | 色窝窝无码一区二区三区色欲 | 成熟女人特级毛片www免费 | 久久精品国产大片免费观看 | 97精品国产97久久久久久免费 | 一区二区传媒有限公司 | 亚洲精品一区三区三区在线观看 | 在线成人www免费观看视频 | 99国产精品白浆在线观看免费 | 人人超人人超碰超国产 | 最新国产乱人伦偷精品免费网站 | 人妻有码中文字幕在线 | 性欧美大战久久久久久久 | 国产精品无码mv在线观看 | 国产在线无码精品电影网 | 亚洲精品一区三区三区在线观看 | 亚洲欧美国产精品专区久久 | 中文精品无码中文字幕无码专区 | 亚洲日韩一区二区三区 | 中文字幕精品av一区二区五区 | 日本熟妇人妻xxxxx人hd | 国产一区二区三区影院 | 无遮挡国产高潮视频免费观看 | 无遮挡啪啪摇乳动态图 | 精品一区二区不卡无码av | 午夜福利试看120秒体验区 | 中文精品久久久久人妻不卡 | 99久久人妻精品免费一区 | 国产一区二区三区影院 | 97人妻精品一区二区三区 | 在线a亚洲视频播放在线观看 | 国产成人无码a区在线观看视频app | 亚洲精品综合五月久久小说 | a片在线免费观看 | 久久精品国产日本波多野结衣 | 国精产品一品二品国精品69xx | 蜜桃视频韩日免费播放 | 又大又硬又黄的免费视频 | 超碰97人人做人人爱少妇 | 亚洲国产一区二区三区在线观看 | 成人一在线视频日韩国产 | 国产真实夫妇视频 | 国产特级毛片aaaaaa高潮流水 | 色五月五月丁香亚洲综合网 | 高潮毛片无遮挡高清免费视频 | 人妻少妇精品久久 | 日韩精品a片一区二区三区妖精 | 伊在人天堂亚洲香蕉精品区 | 亚洲综合另类小说色区 | 亚洲精品鲁一鲁一区二区三区 | 国产成人精品久久亚洲高清不卡 | 永久黄网站色视频免费直播 | 5858s亚洲色大成网站www | 久久久无码中文字幕久... | 久久这里只有精品视频9 | 久久久中文字幕日本无吗 | 成人动漫在线观看 | 女人被爽到呻吟gif动态图视看 | 亚洲经典千人经典日产 | 亚洲精品中文字幕乱码 | 欧美 亚洲 国产 另类 | 少妇激情av一区二区 | 国产性生交xxxxx无码 | 国产明星裸体无码xxxx视频 | 亚洲欧美国产精品专区久久 | 亚洲阿v天堂在线 | 精品人妻人人做人人爽夜夜爽 | 国产精品无套呻吟在线 | 亚洲精品一区二区三区大桥未久 | 亚洲国产午夜精品理论片 | 亚洲 激情 小说 另类 欧美 | 在线精品亚洲一区二区 | 亚洲自偷自偷在线制服 | 精品无码成人片一区二区98 | 曰韩无码二三区中文字幕 | 久久99精品久久久久久 | 国产精品美女久久久网av | 啦啦啦www在线观看免费视频 | 天天燥日日燥 | av人摸人人人澡人人超碰下载 | 欧美日韩人成综合在线播放 | 久9re热视频这里只有精品 | 久久亚洲中文字幕无码 | 妺妺窝人体色www婷婷 | 国产精品久久久久9999小说 | 黑人大群体交免费视频 | 亚洲 日韩 欧美 成人 在线观看 | 精品无人区无码乱码毛片国产 | 人人爽人人澡人人高潮 | 成 人 网 站国产免费观看 | 亚洲精品中文字幕乱码 | 欧美日本免费一区二区三区 | 久久精品中文字幕大胸 | 亚洲爆乳精品无码一区二区三区 | 夜精品a片一区二区三区无码白浆 | 在线看片无码永久免费视频 | 伊人久久大香线焦av综合影院 | 亚洲高清偷拍一区二区三区 | 国产午夜无码视频在线观看 | www国产亚洲精品久久久日本 | 国产精品亚洲一区二区三区喷水 | 亚洲成a人片在线观看无码 | 欧美大屁股xxxxhd黑色 | 无码中文字幕色专区 | 中文字幕av日韩精品一区二区 | 国产极品美女高潮无套在线观看 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 精品国产乱码久久久久乱码 | 久久久无码中文字幕久... | 无码精品人妻一区二区三区av | 最近免费中文字幕中文高清百度 | 午夜精品久久久内射近拍高清 | 欧洲精品码一区二区三区免费看 | 青青草原综合久久大伊人精品 | 67194成是人免费无码 | 亚洲欧洲日本综合aⅴ在线 | 久久久久久久人妻无码中文字幕爆 | 欧美日韩人成综合在线播放 | 国产麻豆精品一区二区三区v视界 | 天天拍夜夜添久久精品 | 秋霞成人午夜鲁丝一区二区三区 | 国产精品亚洲综合色区韩国 | 暴力强奷在线播放无码 | 无套内谢的新婚少妇国语播放 | 夜夜影院未满十八勿进 | 日韩人妻少妇一区二区三区 | 老太婆性杂交欧美肥老太 | 国产内射爽爽大片视频社区在线 | 国内精品久久毛片一区二区 | 国产两女互慰高潮视频在线观看 | 国产成人无码午夜视频在线观看 | 国产亚洲日韩欧美另类第八页 | 欧美精品免费观看二区 | 国产成人综合在线女婷五月99播放 | 日本又色又爽又黄的a片18禁 | 成年美女黄网站色大免费全看 | 亚洲中文字幕成人无码 | 四虎国产精品一区二区 | 国产精品久免费的黄网站 | 国产高清av在线播放 | 亚洲 欧美 激情 小说 另类 | 在线精品国产一区二区三区 | 免费男性肉肉影院 | 国内揄拍国内精品少妇国语 | 色噜噜亚洲男人的天堂 | 免费无码午夜福利片69 | 激情五月综合色婷婷一区二区 | 亚洲熟妇色xxxxx欧美老妇y | 精品无码一区二区三区的天堂 | 久久这里只有精品视频9 | 麻豆国产丝袜白领秘书在线观看 | 亚洲成色在线综合网站 | 色老头在线一区二区三区 | 国产亚洲精品久久久久久国模美 | 国产午夜精品一区二区三区嫩草 | 久久精品人人做人人综合试看 | 日日干夜夜干 | 中文字幕av伊人av无码av | 亚洲成av人片在线观看无码不卡 | 无遮挡啪啪摇乳动态图 | 四虎国产精品免费久久 | 国产在线无码精品电影网 | 四虎永久在线精品免费网址 | 亚洲经典千人经典日产 | 国产亚洲精品精品国产亚洲综合 | 国产三级精品三级男人的天堂 | 波多野结衣av一区二区全免费观看 | 老熟女乱子伦 | 又大又硬又黄的免费视频 | 久9re热视频这里只有精品 | 亚洲综合久久一区二区 | 日韩精品成人一区二区三区 | 精品欧洲av无码一区二区三区 | 蜜桃视频插满18在线观看 | 亚洲精品国产a久久久久久 | 国产人妻人伦精品1国产丝袜 | 无遮挡啪啪摇乳动态图 | 强奷人妻日本中文字幕 | 国产人妻久久精品二区三区老狼 | 国产麻豆精品一区二区三区v视界 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 国产综合久久久久鬼色 | 玩弄少妇高潮ⅹxxxyw | 全黄性性激高免费视频 | 天天拍夜夜添久久精品 | a国产一区二区免费入口 | 又色又爽又黄的美女裸体网站 | av无码不卡在线观看免费 | 久久成人a毛片免费观看网站 | 一个人看的www免费视频在线观看 | 无码精品人妻一区二区三区av | 亚洲成av人片天堂网无码】 | 熟妇激情内射com | 扒开双腿疯狂进出爽爽爽视频 | 国产精品美女久久久网av | 久久人人爽人人爽人人片av高清 | 久久久中文久久久无码 | 天堂亚洲免费视频 | 亚洲gv猛男gv无码男同 | 久久天天躁夜夜躁狠狠 | 久久亚洲中文字幕精品一区 | 亚洲综合无码一区二区三区 | 精品乱码久久久久久久 | 2019nv天堂香蕉在线观看 | 国产成人午夜福利在线播放 | 久久综合狠狠综合久久综合88 | 亚洲国产欧美日韩精品一区二区三区 | 婷婷五月综合缴情在线视频 | 欧美日韩久久久精品a片 | 国精产品一品二品国精品69xx | 偷窥日本少妇撒尿chinese | 亚洲国产精品久久人人爱 | 成人无码精品一区二区三区 | 国产精品久免费的黄网站 | 中文字幕无码日韩欧毛 | 成人性做爰aaa片免费看 | 久久久www成人免费毛片 | 中文字幕乱码人妻二区三区 | 国产小呦泬泬99精品 | 国内少妇偷人精品视频免费 | 欧美成人免费全部网站 | 亚洲春色在线视频 | 四虎影视成人永久免费观看视频 | 亚洲一区二区三区在线观看网站 | 国产无av码在线观看 | 3d动漫精品啪啪一区二区中 | 中文字幕日韩精品一区二区三区 | 高清不卡一区二区三区 | 国产综合在线观看 | 人人超人人超碰超国产 | 亚洲综合无码久久精品综合 | 免费国产成人高清在线观看网站 | 伊人久久大香线蕉午夜 | 欧美熟妇另类久久久久久多毛 | 曰本女人与公拘交酡免费视频 | 亚洲色成人中文字幕网站 | 亚洲国产综合无码一区 | 99精品久久毛片a片 | 欧美自拍另类欧美综合图片区 | 日日噜噜噜噜夜夜爽亚洲精品 | 少妇被粗大的猛进出69影院 | 亚洲人成无码网www | 鲁鲁鲁爽爽爽在线视频观看 | 亚洲欧美综合区丁香五月小说 | 99久久婷婷国产综合精品青草免费 | 中文字幕色婷婷在线视频 | 永久黄网站色视频免费直播 | 国产69精品久久久久app下载 | 国产精品久免费的黄网站 | 午夜福利电影 | 久久综合九色综合97网 | 特大黑人娇小亚洲女 | 成人免费视频一区二区 | 天天拍夜夜添久久精品大 | 久久伊人色av天堂九九小黄鸭 | 亚洲精品久久久久久久久久久 | 无码人妻精品一区二区三区不卡 | 捆绑白丝粉色jk震动捧喷白浆 | 国产三级精品三级男人的天堂 | 国产色视频一区二区三区 | 精品无码成人片一区二区98 | 色婷婷av一区二区三区之红樱桃 | 国产超碰人人爽人人做人人添 | 无码中文字幕色专区 | 亚洲精品国偷拍自产在线麻豆 | 老熟女重囗味hdxx69 | 无码av最新清无码专区吞精 | 少妇激情av一区二区 | 奇米影视7777久久精品人人爽 | 男女猛烈xx00免费视频试看 | 亚洲精品国产第一综合99久久 | 欧美熟妇另类久久久久久多毛 | 国产三级精品三级男人的天堂 | 久久久久久久人妻无码中文字幕爆 | 久久综合给合久久狠狠狠97色 | 无码国产激情在线观看 | 漂亮人妻洗澡被公强 日日躁 | 久久人人爽人人人人片 | 国产真实伦对白全集 | 亚洲精品久久久久久久久久久 | 精品国产国产综合精品 | 色欲综合久久中文字幕网 | 狂野欧美性猛xxxx乱大交 | 少妇的肉体aa片免费 | 久久成人a毛片免费观看网站 | 久久精品国产精品国产精品污 | 国产va免费精品观看 | 高清国产亚洲精品自在久久 | 亚洲 日韩 欧美 成人 在线观看 | 欧美xxxx黑人又粗又长 | 国产午夜福利100集发布 | 国产女主播喷水视频在线观看 | 在线看片无码永久免费视频 | 国产精品福利视频导航 | 一区二区传媒有限公司 | 给我免费的视频在线观看 | 亚洲另类伦春色综合小说 | 成人综合网亚洲伊人 | 国产又爽又黄又刺激的视频 | 天天拍夜夜添久久精品 | 中文字幕人妻无码一夲道 | 亚洲人成影院在线无码按摩店 | 曰韩少妇内射免费播放 | 一本久久a久久精品亚洲 | 99在线 | 亚洲 | 亚洲熟妇色xxxxx欧美老妇 | 亚洲精品鲁一鲁一区二区三区 | 狠狠cao日日穞夜夜穞av | 四虎4hu永久免费 | 全黄性性激高免费视频 | 奇米影视7777久久精品人人爽 | 久久国产36精品色熟妇 | 噜噜噜亚洲色成人网站 | 亚洲区欧美区综合区自拍区 | 亚洲色成人中文字幕网站 | 中文字幕无码日韩欧毛 | 国产精品va在线观看无码 | 亚洲色无码一区二区三区 | 亚洲成色在线综合网站 | 玩弄人妻少妇500系列视频 | 国产亚洲精品久久久久久 | 国产一区二区三区精品视频 | 99riav国产精品视频 | 少女韩国电视剧在线观看完整 | 国产成人精品必看 | 亚洲精品一区国产 | 亚洲国产精品一区二区美利坚 | 夜夜影院未满十八勿进 | 夜夜躁日日躁狠狠久久av | 欧美日韩色另类综合 | 久久久久久亚洲精品a片成人 | 国产无套内射久久久国产 | 少妇邻居内射在线 | 丰满人妻翻云覆雨呻吟视频 | 青青久在线视频免费观看 | 欧美xxxxx精品 | 欧美丰满熟妇xxxx性ppx人交 |