日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring学习总结(一)——Spring实现IoC的多种方式

發布時間:2025/3/20 javascript 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring学习总结(一)——Spring实现IoC的多种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、Spring框架概述

Spring是一個開源免費的框架,為了解決企業應用開發的復雜性而創建。Spring框架是一個輕量級的解決方案,可以一站式地構建企業級應用。Spring是模塊化的,所以可以只使用其中需要的部分。可以在任何web框架上使用控制反轉(IoC),也可以只使用Hibernate集成代碼或JDBC抽象層。它支持聲明式事務管理、通過RMI或web服務實現遠程訪問,并可以使用多種方式持久化數據。它提供了功能全面的MVC框架,可以透明地集成AOP到軟件中。

Spring被設計為非侵入式的,這意味著你的域邏輯代碼通常不會依賴于框架本身。在集成層(比如數據訪問層),會存在一些依賴同時依賴于數據訪問技術和Spring,但是這些依賴可以很容易地從代碼庫中分離出來。

Spring框架是基于Java平臺的,它為開發Java應用提供了全方位的基礎設施支持,并且它很好地處理了這些基礎設施,所以你只需要關注你的應用本身即可。

Spring可以使用POJO(普通的Java對象,plain old java objects)創建應用,并且可以將企業服務非侵入式地應用到POJO。這項功能適用于Java SE編程模型以及全部或部分的Java EE。

那么,做為開發者可以從Spring獲得哪些好處呢?

不用關心事務API就可以執行數據庫事務;

不用關心遠程API就可以使用遠程操作;

不用關心JMX API就可以進行管理操作;

不用關心JMS API就可以進行消息處理。

①JMX,Java Management eXtension,Java管理擴展,是一個為應用程序、設備、系統等植入管理功能的框架。JMX可以跨越一系列異構操作系統平臺、系統體系結構和網絡傳輸協議,靈活的開發無縫集成的系統、網絡和服務管理應用。

②JMS,Java Message Service,Java消息服務,是Java平臺上有關面向消息中間件(MOM)的技術規范,它便于消息系統中的Java應用程序進行消息交換,并且通過提供標準的產生、發送、接收消息的接口簡化企業應用的開發。

一句話概括:Spring是一個輕量級的控制反轉(IoC)和面向切面(AOP)的容器(框架)。

1.1、資源

官網: http://spring.io

文檔: https://docs.spring.io/spring/docs/current/spring-framework-reference/、 https://github.com/waylau/spring-framework-4-reference

中文幫助: http://spring.cndocs.ml/

框架下載地址: http://repo.springsource.org/libs-release-local/org/springframework/spring/

教程: http://www.yiibai.com/spring

Git: https://github.com/spring-projects

源碼: https://github.com/spring-projects/spring-framework

Jar包: https://github.com/spring-projects/spring-framework/releases

1.2、Spring歷史

2002年,Rod Jahnson在《Expert One-on-One J2EE Design and Development》書中首次推出了Spring框架雛形interface21框架。

2004年3月24日,Spring框架以interface21框架為基礎,經過重新設計,發布了1.0正式版。

從2004年3月到現在,已經經歷了1.0、1.1、1.2、2.0、2.5、3.0、3.1幾個主要的版本

3.2.0版發布 2013年5月5日13:53?

3.2.10版發布 2014年7月15日23:58

3.2.9版發布 2014年5月20日12:22

4.0.0版發布 2013年12月12日07:50

4.0.1版發布 2014年1月28日20:55

4.1.6版發布 2015年3月25日16:40

4.2.2版發布 2015年10月15日12:57

4.2.5版發布 2016年2月25日09:28

4.3.5版發布 2016年12月21日11:34

4.3.6版發布 2017年1月25日14:05

4.3.8版發布 2017年4月18日13:49

4.3.9版發布 2017年6月7日19:29

5.0.0版發布 2017年9月28日11:28

5.0.1版發布 2017年10月24日15:14

1.3、框架特征與功能

輕量:從大小與開銷兩方面而言Spring都是輕量的。完整的Spring框架可以在一個大小只有1MB多的JAR文件里發布。并且Spring所需的處理開銷也是微不足道的。此外,Spring是非侵入式的:典型地,Spring應用中的對象不依賴于Spring的特定類。

控制反轉Ioc:Spring通過一種稱作控制反轉(IoC)的技術促進了低耦合。當應用了IoC,一個對象依賴的其它對象會通過被動的方式傳遞進來,而不是這個對象自己創建或者查找依賴對象。你可以認為IoC與JNDI相反——不是對象從容器中查找依賴,而是容器在對象初始化時不等對象請求就主動將依賴傳遞給它。

面向切面Aop:Spring提供了面向切面編程的豐富支持,允許通過分離應用的業務邏輯與系統級服務(例如審計(auditing)和事務(transaction)管理)進行內聚性的開發。應用對象只實現它們應該做的——完成業務邏輯——僅此而已。它們并不負責(甚至是意識)其它的系統級關注點,例如日志或事務支持。

容器:Spring包含并管理應用對象的配置和生命周期,在這個意義上它是一種容器,你可以配置你的每個bean如何被創建——基于一個可配置原型(prototype),你的bean可以創建一個單獨的實例或者每次需要時都生成一個新的實例——以及它們是如何相互關聯的。然而,Spring不應該被混同于傳統的重量級的EJB容器,它們經常是龐大與笨重的,難以使用。

框架:Spring可以將簡單的組件配置、組合成為復雜的應用。在Spring中,應用對象被聲明式地組合,典型地是在一個XML文件里。Spring也提供了很多基礎功能(事務管理、持久化框架集成等等),將應用邏輯的開發留給了你。

MVC:Spring的作用是整合,但不僅僅限于整合,Spring 框架可以被看做是一個企業解決方案級別的框架,Spring MVC是一個非常受歡迎的輕量級Web框架。

所有Spring的這些特征使你能夠編寫更干凈、更可管理、并且更易于測試的代碼。它們也為Spring中的各種模塊提供了基礎支持。

1.4、Spring組成

Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在核心容器之上,核心容器定義了創建、配置和管理 bean 的方式

組成 Spring 框架的每個模塊(或組件)都可以單獨存在,或者與其他一個或多個模塊聯合實現。每個模塊的功能如下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是?BeanFactory,它是工廠模式的實現。BeanFactory?使用控制反轉(IOC) 模式將應用程序的配置和依賴性規范與實際的應用程序代碼分開。
  • Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。
  • Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何對象支持 AOP。Spring AOP 模塊為基于 Spring 的應用程序中的對象提供了事務管理服務。通過使用 Spring AOP,不用依賴 EJB 組件,就可以將聲明性事務管理集成到應用程序中。
  • Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,并且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。
  • Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。
  • Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上,為基于 Web 的應用程序提供了上下文。所以,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作。
  • Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口,MVC 框架變成為高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring 框架的功能可以用在任何 J2EE 服務器中,大多數功能也適用于不受管理的環境。Spring 的核心要點是:支持不綁定到特定 J2EE 服務的可重用業務和數據訪問對象。毫無疑問,這樣的對象可以在不同 J2EE 環境 (Web 或 EJB)、獨立應用程序、測試環境之間重用。

Spring是一個開源的框架,現在的Spring框架構成了一個體系平臺,通過Spring的官方網站http://www.springsource.org可以了解到,圍繞著Spring框架本身,還有許多其他優秀的項目:

SpringFramework(Core):核心項目

Spring Web Flow:工作流項目

Spring Security:安全項目

Spring Batch:批量數據處理項目

Spring Android:Android系統支持項目

Spring Social:社交項目

1.5、Spring Boot與Spring Cloud

Spring Boot 是 Spring 的一套快速配置腳手架,可以基于Spring Boot 快速開發單個微服務,Spring Cloud是一個基于Spring Boot實現的云應用開發工具;Spring Boot專注于快速、方便集成的單個微服務個體,Spring Cloud關注全局的服務治理框架;Spring Boot使用了約束優于配置的理念,很多集成方案已經幫你選擇好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot來實現,Spring Boot可以離開Spring Cloud獨立使用開發項目,但是Spring Cloud離不開Spring Boot,屬于依賴的關系。

SpringBoot在SpringClound中起到了承上啟下的作用,如果你要學習SpringCloud必須要學習SpringBoot。

二、IoC基礎

控制反轉IoC(Inversion of Control),是一種設計思想,DI(依賴注入)是實現IoC的一種方法,也有人認為DI只是IoC的另一種說法。沒有IoC的程序中我們使用面向對象編程對象的創建與對象間的依賴關系完全硬編碼在程序中,對象的創建由程序自己控制,控制反轉后將對象的創建轉移給第三方,個人認為所謂控制反轉就是:獲得依賴對象的方式反轉了

IoC是Spring框架的核心內容,使用多種方式完美的實現了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實現IoC。Spring容器在初始化時先讀取配置文件,根據配置文件或元數據創建與組織對象存入容器中,程序使用時再從Ioc容器中取出需要的對象。

采用XML方式配置Bean的時候,Bean的定義信息是和實現分離的,而采用注解的方式可以把兩者合為一體,Bean的定義信息直接以注解的形式定義在實現類中,從而達到了零配置的目的。

控制反轉是一種通過描述(XML或注解)并通過第三方去生產或獲取特定對象的方式。在Spring中實現控制反轉的是IoC容器,其實現方法是依賴注入(Dependency Injection,DI)。

三、使用XML配置的方式實現IOC

假設項目中需要完成對圖書的數據訪問服務,我們定義好了IBookDAO接口與BookDAO實現類

創建maven項目:

IBookDAO接口如下:

package com.zhangguo.Spring051.ioc01;/*** 圖書數據訪問接口*/ public interface IBookDAO {/*** 添加圖書*/public String addBook(String bookname); }

BookDAO實現類如下:

package com.zhangguo.Spring051.ioc01;/*** 圖書數據訪問實現類*/ public class BookDAO implements IBookDAO {public String addBook(String bookname) {return "添加圖書"+bookname+"成功!";} }

Maven項目的pom.xml如下:

<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.zhangguo</groupId><artifactId>Spring051</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>Spring051</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>4.3.0.RELEASE</spring.version></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope><version>4.10</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.4</version></dependency></dependencies> </project>

業務類BookService如下:

package com.zhangguo.Spring051.ioc01;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 圖書業務類*/ public class BookService {IBookDAO bookDAO;public BookService() {//容器ApplicationContext ctx=new ClassPathXmlApplicationContext("IOCBeans01.xml");//從容器中獲得id為bookdao的beanbookDAO=(IBookDAO)ctx.getBean("bookdao");}public void storeBook(String bookname){System.out.println("圖書上貨");String result=bookDAO.addBook(bookname);System.out.println(result);} }

?容器的配置文件IOCBeans01.xml如下:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="bookdao" class="com.zhangguo.Spring051.ioc01.BookDAO"></bean> </beans>

測試類Test如下:

package com.zhangguo.Spring051.ioc01;public class Test {@org.junit.Testpublic void testStoreBook(){BookService bookservice=new BookService();bookservice.storeBook("《Spring MVC權威指南 第一版》");} }

運行結果:

3.1、使用無參構造方法創建對象

如下所示,則上下文會使用無參構造方法創建對象

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="tom" class="spring02.Student"></bean> </beans>

3.2、使用有參構造方法創建對象

Person.java

package spring02;/***/ public abstract class Person {public String name; }

Student.java

package spring02;/**學生*/ public class Student extends Person {/**身高*/public int height;/**有參構造方法*/public Student(String name,int height){this.name=name;this.height=height;}@Overridepublic String toString() {return "Student{" + "height=" + height+",name="+name +'}';} }

School.java

package spring02;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class School {public static void main(String[] args) {//IoC容器ApplicationContext ctx=new ClassPathXmlApplicationContext("bookbean01.xml","beans02.xml");//從容器中獲取對象Person tom=ctx.getBean("tom",Person.class);System.out.println(tom);} }

配置文件beans02.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="tom" class="spring02.Student"><constructor-arg name="name" value="張柏川"></constructor-arg><constructor-arg name="height" value="195"></constructor-arg></bean> </beans>

運行結果:

注意:如果在使用構造方法時不想通過參數名稱指定參數則可以直接使用索引,如:

<bean id="rose" class="spring02.Student"><constructor-arg index="0" value="張柏芝"></constructor-arg><constructor-arg index="1" value="196"></constructor-arg></bean>

3.3、通過屬性賦值

Address地址類:

package spring02;/**地址*/ public class Address {/**國家*/private String country;/**城市*/private String city;public Address() {}public Address(String country, String city) {this.country = country;this.city = city;}@Overridepublic String toString() {return "Address{" +"country='" + country + '\'' +", city='" + city + '\'' +'}';}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getCity() {return city;}public void setCity(String city) {this.city = city;} }

配置文件beans02.xml:

<bean name="zhuhai" class="spring02.Address"><property name="country" value="中國"></property><property name="city" value="珠海"></property></bean>

測試代碼:

package spring02;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class School {public static void main(String[] args) {//IoC容器ApplicationContext ctx=new ClassPathXmlApplicationContext("bookbean01.xml","beans02.xml");//從容器中獲取對象Person tom=ctx.getBean("rose",Person.class);Address zhuhai=ctx.getBean("zhuhai",Address.class);System.out.println(zhuhai);} }

運行結果:

便捷方式:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="mark" class="entities.Person" p:height="100" p:name="mark"></bean> </beans>

?

3.4、對象引用

你可以使用id 或(和) name 屬性來指定bean的標識符

Person

package spring02;/***/ public abstract class Person {/**姓名*/public String name;/**地址*/public Address address;public String getName() {return name;}public void setName(String name) {this.name = name;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;} }

Student

package spring02;/**學生*/ public class Student extends Person {/**身高*/public int height;/**有參構造方法*/public Student(String name,int height){this.name=name;this.height=height;}/**有參構造方法*/public Student(String name,int height,Address address){this.name=name;this.height=height;this.address=address;}@Overridepublic String toString() {return "Student{" + "height=" + height+",name="+name +'}'+address;} }

配置文件

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean name="zhuhai" class="spring02.Address"><property name="country" value="中國"></property><property name="city" value="珠海"></property></bean><bean id="tom" class="spring02.Student"><constructor-arg name="name" value="張柏川"></constructor-arg><constructor-arg name="height" value="195"></constructor-arg><constructor-arg name="address" ref="zhuhai"></constructor-arg></bean><bean id="rose" class="spring02.Student"><constructor-arg index="0" value="張柏芝"></constructor-arg><constructor-arg index="1" value="196"></constructor-arg><constructor-arg index="2" ref="zhuhai"></constructor-arg></bean> </beans>

測試代碼:

package spring02;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class School {public static void main(String[] args) {//IoC容器ApplicationContext ctx=new ClassPathXmlApplicationContext("bookbean01.xml","beans02.xml");//從容器中獲取對象Person tom=ctx.getBean("tom",Person.class);Person rose=ctx.getBean("rose",Person.class);//Address zhuhai=ctx.getBean("zhuhai",Address.class); System.out.println(tom);System.out.println(rose);} }

運行結果:

3.5、對象作用域

從容器中取回的對象默認是單例的:

Person roseA=ctx.getBean("rose",Person.class);Person roseB=ctx.getBean("rose",Person.class);//Address zhuhai=ctx.getBean("zhuhai",Address.class); System.out.println(tom);System.out.println(roseA==roseB);

運行結果:

使用scope屬性可以指定作用域

<bean id="rose" class="spring02.Student" scope="prototype"><constructor-arg index="0" value="張柏芝"></constructor-arg><constructor-arg index="1" value="196"></constructor-arg><constructor-arg index="2" ref="zhuhai"></constructor-arg></bean>

測試代碼:

//從容器中獲取對象Person tom=ctx.getBean("tom",Person.class);Person roseA=ctx.getBean("rose",Person.class);Person roseB=ctx.getBean("rose",Person.class);//Address zhuhai=ctx.getBean("zhuhai",Address.class); System.out.println(tom);System.out.println(roseA==roseB);

?運行結果:

3.6、延遲初始化bean

ApplicationContext實現的默認行為就是再啟動時將所有 singleton?bean提前進行實例化。 通常這樣的提前實例化方式是好事,因為配置中或者運行環境的錯誤就會被立刻發現,否則可能要花幾個小時甚至幾天。如果你不想 這樣,你可以將單例bean定義為延遲加載防止它提前實例化。延遲初始化bean會告訴Ioc容器在第一次需要的時候才實例化而不是在容器啟動時就實例化。

在XML配置文件中,延遲初始化通過<bean/>元素的lazy-init屬性進行控制,比如:

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/> <bean name="not.lazy" class="com.foo.AnotherBean"/>

XML:

<bean id="mark" class="entities.Person" lazy-init="true" scope="prototype"><property name="name" value="mark"></property><property name="height" value="185"></property></bean>

用例:

@Testpublic void testMethod3() throws Exception {//通過spring配置文件初始化一個容器ApplicationContext ctx=new ClassPathXmlApplicationContext("springCfg.xml");Thread.sleep(2000);Person mark1=ctx.getBean("mark",Person.class);Thread.sleep(2000);Person mark2=ctx.getBean("mark",Person.class);System.out.println(mark1==mark2);}

結果:

3.7、回調方法

3.7.1、初始化回調函數

配置文件:

<bean id="tom" class="spring02.Student" init-method="init" destroy-method="over"><constructor-arg name="name" value="張柏川"></constructor-arg><constructor-arg name="height" value="195"></constructor-arg><constructor-arg name="address" ref="zhuhai"></constructor-arg></bean>

Student類:

package spring02;import java.io.File;/**學生*/ public class Student extends Person {/**身高*/public int height;/**有參構造方法*/public Student(String name,int height){this.name=name;this.height=height;}/**有參構造方法*/public Student(String name,int height,Address address){this.name=name;this.height=height;this.address=address;}@Overridepublic String toString() {return "Student{" + "height=" + height+",name="+name +'}'+address;}public void init(){System.out.println("對象被創建");}public void over(){System.out.println("對象被回收");}}

運行結果:

3.7.2、析構回調函數

實現 org.springframework.beans.factory.DisposableBean 接口,允許一個bean當容器需要其銷毀時獲得一次回調。 DisposableBean 接口也只規定了一個方法:

void destroy() throws Exception;

建議不使用 DisposableBean 回調接口,因為會與Spring耦合。使用@PreDestroy 注解或者指定一個普通的方法,但能由bean定義支持。基于XML配置的元數據,使用 <bean/> 的 destroy-method 屬性。例如,下面的定義:

<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>

示例

public class ExampleBean {public void cleanup() { // do some destruction work (like releasing pooled connections) } }

與下面效果相同:

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>

示例:

public class AnotherExampleBean implements DisposableBean {public void destroy() {// do some destruction work (like releasing pooled connections) }}

但是不與Spring耦合。

四、使用Spring注解配置IOC

?上一個示例是使用傳統的xml配置完成IOC的,如果內容比較多則配置需花費很多時間,通過注解可以減輕工作量,但注解后修改要麻煩一些,偶合度會增加,應該根據需要選擇合適的方法。

4.1、修改BookDAO

package com.zhangguo.Spring051.ioc02;import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository;/*** 圖書數據訪問實現類*/ @Component("bookdaoObj") public class BookDAO implements IBookDAO {public String addBook(String bookname) {return "添加圖書"+bookname+"成功!";} }

在類上增加了一個注解Component,在類的開頭使用了@Component注解,它可以被Spring容器識別,啟動Spring后,會自動把它轉成容器管理的Bean。

除了@Component外,Spring提供了3個功能基本和@Component等效的注解,分別對應于用于對DAO,Service,和Controller進行注解。
1:@Repository 用于對DAO實現類進行注解。
2:@Service 用于對業務層注解,但是目前該功能與 @Component 相同。
3:@Constroller用于對控制層注解,但是目前該功能與 @Component 相同。

4.2、修改BookService

package com.zhangguo.Spring051.ioc02;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;/*** 圖書業務類*/ @Component public class BookService {IBookDAO bookDAO;public void storeBook(String bookname){//容器ApplicationContext ctx=new ClassPathXmlApplicationContext("IOCBeans02.xml");//從容器中獲得id為bookdao的beanbookDAO=(IBookDAO)ctx.getBean("bookdaoObj");System.out.println("圖書上貨");String result=bookDAO.addBook(bookname);System.out.println(result);} }

將構造方法中的代碼直接寫在了storeBook方法中,避免循環加載的問題。

4.3、修改IOC配置文件IOCBeans02.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:component-scan base-package="com.zhangguo.Spring051.ioc02"></context:component-scan> </beans>

粗體字是新增的xml命名空間與模式約束文件位置。增加了注解掃描的范圍,指定了一個包,可以通過屬性設置更加精確的范圍如:

<context>標記常用屬性配置:
resource-pattern:對指定的基包下面的子包進行選取
<context>子標記:
include-filter:指定需要包含的包
exclude-filter:指定需要排除的包
<!-- 自動掃描com.zhangguo.anno.bo中的類進行掃描?-->
<context:component-scan base-package="com.zhangguo.anno" resource-pattern="bo/*.class" />

<context:component-scan base-package="com.zhangguo.anno" >

? <context:include-filter type="aspectj“ expression="com.zhangguo.anno.dao.*.*"/>
? <context:exclude-filter type=“aspectj” expression=“com.zhangguo.anno.entity.*.*”/>

</context:component-scan>

include-filter表示需要包含的目標類型,exclude-filter表示需要排除的目標類型,type表示采的過濾類型,共有如下5種類型:

Filter TypeExamples ExpressionDescription
annotationorg.example.SomeAnnotation注解了SomeAnnotation的類
assignableorg.example.SomeClass所有擴展或者實現SomeClass的類
aspectjorg.example..*Service+AspectJ語法表示org.example包下所有包含Service的類及其子類
regexorg\.example\.Default.*Regelar Expression,正則表達式
customorg.example.MyTypeFilter通過代碼過濾,實現org.springframework.core.type.TypeFilter接口

expression表示過濾的表達式。

<!-- 1、如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類 --><context:component-scan base-package="com.zhangguo.Spring051"resource-pattern="ioc04/A*.class"></context:component-scan>

只掃描com.zhangguo.Spring051.ioc04下所有名稱以A開始的類。

<!--2、掃描注解了org.springframework.stereotype.Repository的類exclude-filter表示排除,include-filter表示包含,可以有多個--><context:component-scan base-package="com.zhangguo.Spring051.ioc04"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" /><context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/></context:component-scan> <!--3、aspectj類型,掃描dao下所有的類,排除entity下所有的類--><context:component-scan base-package="com.zhangguo.anno" ><context:include-filter type="aspectj" expression="com.zhangguo.anno.dao.*.*"/><context:exclude-filter type="aspectj" expression="com.zhangguo.anno.entity.*.*"/> </context:component-scan>

測試類

package com.zhangguo.Spring051.ioc02;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {@org.junit.Testpublic void testStoreBook(){//容器ApplicationContext ctx=new ClassPathXmlApplicationContext("IOCBeans02.xml");BookService bookservice=ctx.getBean(BookService.class);bookservice.storeBook("《Spring MVC權威指南 第二版》");} }

運行結果:

4.4、簡單示例

IBookDao接口

package spring11;public interface IBookDao {void add(); }

BookDao實現類

package spring11;import org.springframework.stereotype.Component;@Component("bookdao") public class BookDao implements IBookDao {public void add() {System.out.println("新增圖書成功!");} }

MSBookDao實現類

package spring11;import org.springframework.stereotype.Component; @Component("bookdao") public class MSBookDao implements IBookDao {public void add() {System.out.println("新增圖書到SQLServer成功!");} }

BookService測試類:

package spring11;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class BookService {public static void main(String[] args) {//容器ApplicationContext ctx=new ClassPathXmlApplicationContext(new String[]{"bookbean11.xml"});//從容器中獲得對象IBookDao dao=ctx.getBean("bookdao",IBookDao.class);dao.add();} }

XML配置:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><bean name="tom" class="spring02.Student" p:name="tom" p:height="224"/><!--指定要掃描的包,如果有多個可以用逗號隔開--><context:component-scan base-package="spring11"><!--使用正則排除以B開頭的類--><context:exclude-filter type="regex" expression="spring11\.B.*"></context:exclude-filter></context:component-scan></beans>

運行結果:

指定兩個bookdao是不正確的,重名了,但是因為在組件掃描中我們排除了一個所有也可以正確運行。

4.5、作用域用scope來指定

默認容器中的bean是單例的:

//從容器中獲得對象IBookDao dao1=ctx.getBean("bookdao",IBookDao.class);IBookDao dao2=ctx.getBean("bookdao",IBookDao.class);System.out.println(dao1==dao2);

結果:

修改成原型

package spring11;import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;@Component("bookdao") @Scope("prototype") public class MSBookDao implements IBookDao {public void add() {System.out.println("新增圖書到SQLServer成功!");} }

結果:

?

用來指定bean的作用域

singleton---單例 ?只創建一個對象。

prototype---原型 ?想創建多少個就創建多少了。

request---針對Web項目,不同的請求創建單獨的Bean對象,同一個請求共享一個Bean。

session---針對Web項目,不同的會話創建單獨的Bean對象,同一個會話共享一個Bean。

4.5 、Lazy延遲初始化Bean

默認情況下Spring IoC容器在初始化時將Bean創建好存放到容器中:

測試:

@Testpublic void testMethod6() throws Exception {//通過spring配置文件初始化一個容器ApplicationContext ctx=new ClassPathXmlApplicationContext("springCfg2.xml");Thread.sleep(6000);IBookDao dao=ctx.getBean("mssql",IBookDao.class);dao.add("<<Java EE>>");}

結果:

此處等待6秒...

增加注解修改成延遲初始化bean

package dao;import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Repository;@Repository("mssql") @Lazy public class SQLServerBookDao implements IBookDao {public SQLServerBookDao() {System.out.println("SQLServerBookDao構造方法被調用");}/*** 添加圖書** @param name*/public void add(String name) {System.out.println("添加圖書到SQLServer數據庫成功:"+name);} }

再次測試結果:

然后

4.6、初始化回調注解與銷毀回調注解

4.6.1、@PostConstruct

@PostConstruct? 初始化方法的注解方式 等同與在XML中聲明init-method=init

package dao;import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Repository;import javax.annotation.PostConstruct;@Repository("mssql") @Lazy public class SQLServerBookDao implements IBookDao {public SQLServerBookDao() {System.out.println("SQLServerBookDao構造方法被調用");}/*** 添加圖書** @param name*/public void add(String name) {System.out.println("添加圖書到SQLServer數據庫成功:"+name);}//init-method callback @PostConstructpublic void init(){System.out.println("SQLServerBookDao初創建完成了");} }

結果

4.6.2、@PreDestroy

@PreDestroy 銷毀方法的注解方式 等同于在XML中聲明destory-method=destory

package dao;import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Repository;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;@Repository("mssql") @Lazy public class SQLServerBookDao implements IBookDao {public SQLServerBookDao() {System.out.println("SQLServerBookDao構造方法被調用");}/*** 添加圖書** @param name*/public void add(String name) {System.out.println("添加圖書到SQLServer數據庫成功:"+name);}//init-method callback @PostConstructpublic void init(){System.out.println("SQLServerBookDao初創建完成了");}//destory-method callback @PreDestroypublic void destory(){System.out.println("SQLServerBookDao準備銷毀了");} }

?

4.7、默認名稱

如果使用Compont注解時不指定名稱,基于@Componet及其擴展(如@Servic和自定義等)標注和classpath-scan定義的Bean,注解有一個value屬性,如果提供了,那么就此Bean的名字。如果不提供。就會使用Spring默認的命名機制,即簡單類名且第一個字母小寫

package spring11;import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;@Component() //未指定名稱 @Scope("prototype") public class MSBookDao implements IBookDao {public void add() {System.out.println("新增圖書到SQLServer成功!");} }

測試:

package spring11;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class BookService {public static void main(String[] args) {//容器ApplicationContext ctx=new ClassPathXmlApplicationContext(new String[]{"bookbean11.xml"});//從容器中獲得對象IBookDao dao1=ctx.getBean("MSBookDao",IBookDao.class);IBookDao dao2=ctx.getBean("MSBookDao",IBookDao.class);System.out.println(dao1==dao2);dao1.add();} }

結果:

在基于XML的配置中bean標簽還有很多屬性,如scope、Lazy、init-method、depends-on、Qualifier等。

從容器中獲取實例時也可以直接根據類型獲取

package spring12;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component;@Component public class BookStore {@AutowiredBookService service;public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("bookbean12.xml");BookStore store =ctx.getBean(BookStore.class);store.service.addNewBook();A a=ctx.getBean("a",A.class);System.out.println(a);} }@Component class A{} @Component class B extends A{}

結果:

默認名稱時需要將首字母小寫,Camel命名規范:

package dao;import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;@Component public class MySqlBookDao implements IBookDao {/*** 添加圖書** @param name*/public void add(String name) {System.out.println("添加圖書到MySQL數據庫成功:"+name);} }

測試:

@Testpublic void testMethod5() throws Exception {//通過spring配置文件初始化一個容器ApplicationContext ctx=new ClassPathXmlApplicationContext("springCfg2.xml");IBookDao bookDao=ctx.getBean("mySqlBookDao",IBookDao.class);bookDao.add("《Spring從入門到精通》");}

結果:

4.6、小結

從配置文件中我們可以看出我們并沒有聲明bookdaoObj與BookService類型的對象,但還是從容器中獲得了實例并成功運行了,原因是:在類的開頭使用了@Component注解,它可以被Spring容器識別,啟動Spring后,會自動把它轉成容器管理的Bean。

五、自動裝配

?從上一個示例中可以看出有兩個位置都使用了ApplicationContext初始化容器后獲得需要的Bean,可以通過自動裝配簡化。

5.1、修改BookDAO

package com.zhangguo.Spring051.ioc03;import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository;/*** 圖書數據訪問實現類*/ @Repository public class BookDAO implements IBookDAO {public String addBook(String bookname) {return "添加圖書"+bookname+"成功!";} }

把注解修改成了Repository,比Component更貼切一些,非必要。

5.2、修改BookService

package com.zhangguo.Spring051.ioc03;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Service;/*** 圖書業務類*/ @Service public class BookService {@AutowiredIBookDAO bookDAO;public void storeBook(String bookname){System.out.println("圖書上貨");String result=bookDAO.addBook(bookname);System.out.println(result);} }

將類BookService上的注解替換成了Service;在bookDao成員變量上增加了一個注解@Autowired,該注解的作用是:可以對成員變量、方法和構造函數進行注解,來完成自動裝配的工作,通俗來說就是會根據類型從容器中自動查到到一個Bean給bookDAO字段。@Autowired是根據類型進行自動裝配的,如果需要按名稱進行裝配,則需要配合@Qualifier。另外可以使用其它注解,@ Resource :等同于@Qualifier,@Inject:等同于@ Autowired。

@Service用于注解業務層組件(我們通常定義的service層就用這個)

@Controller用于注解控制層組件(如struts中的action)

@Repository用于注解數據訪問組件,即DAO組件

@Component泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行注解。

裝配注解主要有:@Autowired、@Qualifier、@Resource,它們的特點是:

1、@Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean才會按照類型來裝配注入;

2、@Autowired默認是按照類型裝配注入的,如果想按照名稱來轉配注入,則需要結合@Qualifier一起使用;

3、@Resource注解是又J2EE提供,而@Autowired是由spring提供,故減少系統對spring的依賴建議使用@Resource的方式;如果Maven項目是1.5的JRE則需換成更高版本的。

4、@Resource和@Autowired都可以書寫注解在字段或者該字段的setter方法之上

5、@Autowired 可以對成員變量、方法以及構造函數進行注釋,而 @Qualifier 的注解對象是成員變量、方法入參、構造函數入參。

6、@Qualifier("XXX") 中的 XX是 Bean 的名稱,所以 @Autowired 和 @Qualifier 結合使用時,自動注入的策略就從 byType 轉變成 byName 了。

7、@Autowired 注釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個,通過屬性required可以設置非必要。

8、@Resource裝配順序
  8.1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
  8.2. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
  8.3. 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
  8.4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配;

package com.zhangguo.Spring051.ioc05;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Service;/*** 圖書業務類*/ @Service public class BookService {public IBookDAO getDaoofbook() {return daoofbook;}/*@Autowired@Qualifier("bookdao02")public void setDaoofbook(IBookDAO daoofbook) {this.daoofbook = daoofbook;}*/@Resource(name="bookdao02")public void setDaoofbook(IBookDAO daoofbook) {this.daoofbook = daoofbook;}/*@Autowired@Qualifier("bookdao02")*/IBookDAO daoofbook;/*public BookService(@Qualifier("bookdao02") IBookDAO daoofbook) {this.daoofbook=daoofbook;}*/public void storeBook(String bookname){System.out.println("圖書上貨");String result=daoofbook.addBook(bookname);System.out.println(result);} }

測試運行

package com.zhangguo.Spring051.ioc03;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {@org.junit.Testpublic void testStoreBook(){//容器ApplicationContext ctx=new ClassPathXmlApplicationContext("IOCBeans03.xml");BookService bookservice=ctx.getBean(BookService.class);bookservice.storeBook("《Spring MVC權威指南 第三版》");} }

運行結果:

5.3、簡單示例

IBookDao

package spring12;/**圖書數據訪問接口*/ public interface IBookDao {/**添加新書*/void save(String name); }

BookDao

package spring12;import org.springframework.stereotype.Repository;/*** 完成圖書數據訪問*/ @Repository public class BookDao implements IBookDao {public void save(String name) {System.out.println("添加圖書" + name + "到數據庫成功!");} }

BookService

package spring12;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service public class BookService {@AutowiredIBookDao bookDao;/**新增一本書*/public void addNewBook(){String bookname="《Spring MVC學習指南》";bookDao.save(bookname);} }

配置bookbean12.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!--指定要掃描的包,如果有多個可以用逗號隔開--><context:component-scan base-package="spring12"></context:component-scan> </beans>

BookStore

package spring12;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component;@Component public class BookStore {@AutowiredBookService service;public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("bookbean12.xml");BookStore store =ctx.getBean(BookStore.class);store.service.addNewBook();} }

測試結果:

5.4、@Qualifier指定名稱

@Qualifier("XXX") 中的 XX是 Bean 的名稱,所以 @Autowired 和 @Qualifier 結合使用時,自動注入的策略就從 byType 轉變成 byName 了。qualifier的意思是合格者,通過這個標示,表明了哪個實現類才是我們所需要的
先看下面這個示例:

package spring13;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;@Service public class QualifierTest {@AutowiredIBookDao dao;public static void main(String[] args) {ApplicationContext ctx =new ClassPathXmlApplicationContext("bookbean13.xml");QualifierTest obj = ctx.getBean(QualifierTest.class);System.out.println(obj.dao);} }interface IBookDao { }@Repository class BookDaoA implements IBookDao { }@Repository class BookDaoB implements IBookDao { }

運行結果:

?

這樣報錯的原因是找到了多個Bean,Spring不知道選擇那一個。使用Qualifier指定名稱

package spring13;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;@Service public class QualifierTest {@Autowired @Qualifier("daoA")IBookDao dao;public static void main(String[] args) {ApplicationContext ctx =new ClassPathXmlApplicationContext("bookbean13.xml");QualifierTest obj = ctx.getBean(QualifierTest.class);System.out.println(obj.dao);} }interface IBookDao { } @Repository("daoA") class BookDaoA implements IBookDao { }@Repository("daoB") class BookDaoB implements IBookDao { }

結果:

5.5、@Resource

@Resource裝配順序
如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配;

package spring13;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;import javax.annotation.Resource;@Service public class ResourceTest { @Resource(name = "carB")ICarDao dao;public static void main(String[] args) {ApplicationContext ctx =new ClassPathXmlApplicationContext("bookbean13.xml");ResourceTest obj = ctx.getBean(ResourceTest.class);System.out.println(obj.dao);} }interface ICarDao { }@Repository("carA") class CarDaoA implements ICarDao { }@Repository("carB") class CarDaoB implements ICarDao { }/* @Resource裝配順序 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配; */ 運行結果:

5.6、多種注入方式

示例:

package spring13;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Scope; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;import javax.annotation.Resource;@Service public class InjectTest {//注入給構造方法 @Autowiredpublic InjectTest(IUserDao dao2) {this.dao2=dao2;}//注入給成員變量,字段 @ResourceIUserDao dao1;IUserDao dao2;IUserDao dao3;IUserDao dao4;//注入給屬性 @Autowiredpublic void setDao3(IUserDao dao3) {this.dao3 = dao3;}//注入給方法參數 @Autowiredpublic void injectDao4(IUserDao dao4, IUserDao dao5) {this.dao4 = dao4;System.out.println(dao5);}public static void main(String[] args) {ApplicationContext ctx =new ClassPathXmlApplicationContext("bookbean13.xml");InjectTest obj = ctx.getBean(InjectTest.class);System.out.println(obj.dao1);System.out.println(obj.dao2);System.out.println(obj.dao3);System.out.println(obj.dao4);} }interface IUserDao { }@Scope("prototype") @Repository class UserDao implements IUserDao { }

結果:

?

六、零配置實現IOC

6.1、綜合示例

所謂的零配置就是不再使用xml文件來初始化容器,使用一個類型來替代,

?IBookDAO代碼如下:

package com.zhangguo.Spring051.ioc06;/*** 圖書數據訪問接口*/ public interface IBookDAO {/*** 添加圖書*/public String addBook(String bookname); }

IBookDAO的實現類BookDAO代碼如下:

package com.zhangguo.Spring051.ioc06;import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository;/*** 圖書數據訪問實現類*/ @Repository public class BookDAO implements IBookDAO {public String addBook(String bookname) {return "添加圖書"+bookname+"成功!";} }

在BookDAO類上注解了@Repository當初始化時該類將被容器管理會生成一個Bean,可以通過構造方法測試。

業務層BookService代碼如下:

package com.zhangguo.Spring051.ioc06;import javax.annotation.Resource;import org.springframework.stereotype.Service;/*** 圖書業務類*/ @Service public class BookService {@ResourceIBookDAO bookDAO;public void storeBook(String bookname){System.out.println("圖書上貨");String result=bookDAO.addBook(bookname);System.out.println(result);} }

類BookService將對容器管理因為注解了@Service,初始化時會生成一個單例的Bean,類型為BookService。在字段bookDAO上注解了@Resource,用于自動裝配,Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean才會按照類型來裝配注入。

新增一個用于替代原xml配置文件的ApplicationCfg類,代碼如下:

package com.zhangguo.Spring051.ioc06;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;/*** 容器的配置類*/ @Configuration @ComponentScan(basePackages="com.zhangguo.Spring051.ioc06") public class ApplicationCfg {@Beanpublic User getUser(){return new User("成功");} }

@Configuration相當于配置文件中的<beans/>,ComponentScan相當于配置文件中的context:component-scan,屬性也一樣設置

,@Bean相當于<bean/>,只能注解在方法和注解上,一般在方法上使用,源碼中描述:@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}),方法名相當于id。中間使用到了User,User類的代碼如下:

package com.zhangguo.Spring051.ioc06;import org.springframework.stereotype.Component;@Component("user1") public class User {public User() {System.out.println("創建User對象");}public User(String msg) {System.out.println("創建User對象"+msg);}public void show(){System.out.println("一個學生對象!");} }

初始化容器的代碼與以前有一些不一樣,具體如下:

package com.zhangguo.Spring051.ioc06;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Test {@org.junit.Testpublic void testStoreBook(){//容器,注解配置應用程序容器,Spring通過反射ApplicationCfg.class初始化容器ApplicationContext ctx=new AnnotationConfigApplicationContext(ApplicationCfg.class);BookService bookservice=ctx.getBean(BookService.class);bookservice.storeBook("《Spring MVC權威指南 第四版》");User user1=ctx.getBean("user1",User.class);user1.show();User getUser=ctx.getBean("getUser",User.class);getUser.show();} }

容器的初始化通過一個類型完成,Spring通過反射ApplicationCfg.class初始化容器,中間user1與getUser是否為相同的Bean呢?

答案是否定的,因為在ApplicationCfg中聲明的方法getUser當相于在xml文件中定義了一個<bean id="getUser" class="..."/>,在User類上注解@Component("user1")相當于另一個<bean id="user1" class="..."/>。

運行結果:

小結:使用零配置和注解雖然方便,不需要編寫麻煩的xml文件,但并非為了取代xml,應該根據實例需要選擇,或二者結合使用,畢竟使用一個類作為容器的配置信息是硬編碼的,不好在發布后修改。

6.2、零配置,由注解指定實例

package spring14;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Repository;public class NoXMLIoC {public static void main(String[] args) {//基于類型的配置ApplicationContext ctx=new AnnotationConfigApplicationContext(AppCfg.class);ICarDao dao1=ctx.getBean(ICarDao.class);dao1.add("Spring Pro");} }interface ICarDao{void add(String name); } @Repository class CarDao implements ICarDao{public void add(String name) {System.out.println("添加"+name+"成功!");} } @Configuration @ComponentScan(basePackages = "spring14") class AppCfg{}

運行結果:

6.3、零配置,由方法指定實例

package spring14;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Repository;public class NoXMLIoC {public static void main(String[] args) {//基于類型的配置ApplicationContext ctx=new AnnotationConfigApplicationContext(AppCfg.class);ICarDao dao2=ctx.getBean("mysqlDao",ICarDao.class);dao2.add("Spring Pro");} }interface ICarDao{void add(String name); } class CarDao implements ICarDao{public void add(String name) {System.out.println("添加"+name+"成功!");} } @Configuration @ComponentScan(basePackages = "spring14") class AppCfg{@BeanICarDao mysqlDao(){ //方法名就是bean的namereturn new CarDao();} }

運行結果:

package spring14;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Repository;public class NoXMLIoC {public static void main(String[] args) {//基于類型的配置ApplicationContext ctx=new AnnotationConfigApplicationContext(AppCfg.class);ICarDao dao1=ctx.getBean("oracleDao",ICarDao.class);dao1.add("Spring Pro Oracle");ICarDao dao2=ctx.getBean("mysqlDao",ICarDao.class);dao2.add("Spring Pro MySQL");System.out.println(dao1==dao2);} }interface ICarDao{void add(String name); } @Repository("oracleDao") class CarDao implements ICarDao{public void add(String name) {System.out.println("添加"+name+"成功!");} } @Configuration @ComponentScan(basePackages = "spring14") class AppCfg{@BeanICarDao mysqlDao(){ //方法名就是bean的namereturn new CarDao();} }

運行結果:

七、通過注解@Value獲取properties配置

@value注解可以實現為對象賦值,可以直接指定值也可以從properties文件中獲取,這里主要講解兩種方式:

7.1、使用XML實現

1、在resource目錄下創建一個properties文件,如db.properties:

2、在Spring配置文件中導入資源文件

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:component-scan base-package="com.zhangguo.spring03.demo.v32"></context:component-scan><!--屬性點位,location用于指定資源位置,ignore-unresolvable忽視不能解析的內容--><context:property-placeholder location="db.properties" ignore-unresolvable="true"></context:property-placeholder> </beans>

3、通過@Value引用資源文件中的內容

package com.zhangguo.spring03.demo.v32;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository;@Component public class DbUtils {@Value("com.jdbc.driver.Oracle")private String driver;@Value("${URL}")private String location;@Value("${userName}")private String uid;@Value("${password}")private String pwd;@Overridepublic String toString() {return "DbUtils{" +"driver='" + driver + '\'' +", location='" + location + '\'' +", uid='" + uid + '\'' +", pwd='" + pwd + '\'' +'}';}public String getDriver() {return driver;}public void setDriver(String driver) {this.driver = driver;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;} }

4、測試

package com.zhangguo.spring03.demo.v32;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Client32 {public static void main(String[] args) {ApplicationContext ctx=new ClassPathXmlApplicationContext("springCfg32.xml");UserDao dao=ctx.getBean(UserDao.class);System.out.println(dao.dbUtils);} }

5、結果

7.2、使用零配置注解方式實現

1、創建配置類

package com.zhangguo.spring03.demo.v33;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.PropertySource;@Configuration @ComponentScan("com.zhangguo.spring03.demo.v33") @PropertySource("db.properties") public class SpringCfg {}

使用@ImportResource可能會產生的異常(前言中不允許有內容):

"C:\Program Files\Java\jdk1.8.0_111\bin\java" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\lib\idea_rt.jar=5997:C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_111\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\rt.jar;C:\Users\Administrator\Desktop\mybatis-generator-gui-0.8.4\Spring02\target\classes;H:\InstallFiles\javaKit\mavenRes\junit\junit\4.12\junit-4.12.jar;H:\InstallFiles\javaKit\mavenRes\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;H:\InstallFiles\javaKit\mavenRes\cglib\cglib\3.2.4\cglib-3.2.4.jar;H:\InstallFiles\javaKit\mavenRes\org\ow2\asm\asm\5.1\asm-5.1.jar;H:\InstallFiles\javaKit\mavenRes\org\apache\ant\ant\1.9.6\ant-1.9.6.jar;H:\InstallFiles\javaKit\mavenRes\org\apache\ant\ant-launcher\1.9.6\ant-launcher-1.9.6.jar;H:\InstallFiles\javaKit\mavenRes\org\springframework\spring-context\4.3.0.RELEASE\spring-context-4.3.0.RELEASE.jar;H:\InstallFiles\javaKit\mavenRes\org\springframework\spring-aop\4.3.0.RELEASE\spring-aop-4.3.0.RELEASE.jar;H:\InstallFiles\javaKit\mavenRes\org\springframework\spring-beans\4.3.0.RELEASE\spring-beans-4.3.0.RELEASE.jar;H:\InstallFiles\javaKit\mavenRes\org\springframework\spring-core\4.3.0.RELEASE\spring-core-4.3.0.RELEASE.jar;H:\InstallFiles\javaKit\mavenRes\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;H:\InstallFiles\javaKit\mavenRes\org\springframework\spring-expression\4.3.0.RELEASE\spring-expression-4.3.0.RELEASE.jar;H:\InstallFiles\javaKit\mavenRes\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar" com.zhangguo.spring03.demo.v33.Client33 十月 22, 2018 11:30:15 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@685f4c2e: startup date [Mon Oct 22 11:30:15 CST 2018]; root of context hierarchy 十月 22, 2018 11:30:17 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [db.properties] 十月 22, 2018 11:30:17 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext refresh 警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 1 in XML document from class path resource [db.properties] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 前言中不允許有內容。 Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 1 in XML document from class path resource [db.properties] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 前言中不允許有內容。at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:399)at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources(ConfigurationClassBeanDefinitionReader.java:346)at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:142)at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116)at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:333)at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:98)at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523)at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)at com.zhangguo.spring03.demo.v33.Client33.main(Client33.java:9) Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 前言中不允許有內容。at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1472)at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:994)at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:76)at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadDocument(XmlBeanDefinitionReader.java:429)at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:391)... 16 moreProcess finished with exit code 1 View Code

2、測試

package com.zhangguo.spring03.demo.v33;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class Client33 {public static void main(String[] args) {ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringCfg.class);UserDao dao=ctx.getBean(UserDao.class);System.out.println(dao.dbUtils);} }

3、結果

7.3、其它方式

假如有以下屬性文件dev.properties, 需要注入下面的tag

tag=123

通過PropertyPlaceholderConfigurer

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="dev.properties" /> </bean>

代碼

@Value("${tag}") private String tag;

通過PreferencesPlaceholderConfigurer

<bean id="appConfig" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="location" value="dev.properties" /> </bean>

代碼:

@Value("${tag}") private String tag;

?


通過PropertiesFactoryBean

<bean id="config" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location" value="dev.properties" /> </bean>

代碼:

@Value("#{config['tag']}") private String tag;

通過util:properties

效果同PropertiesFactoryBean一樣

代碼:

@Value("#{config['tag']}") private String tag;

八、示例下載

https://git.coding.net/zhangguo5/Spring.git

點擊下載

https://git.coding.net/zhangguo5/c6_2_SpringIoC.git
https://git.dev.tencent.com/zhangguo5/Spring01.git

九、視頻

https://www.bilibili.com/video/av16071354/

十、作業

第一次作業

1.1、請完成所有基于XML配置Ioc上課示例。

1.2、請學會使用幫助文檔

1.3、請定義一個Animal動物類(名稱name,重量weight),定義兩個Animal子類貓Cat(品種type)與狗Dog(顏色color)

1.4、以Animal、Cat、Dog為基礎練習3.1-3.6的所有知識點

1.5、請寫一個微型的Ioc框架(MiniIoc),實現最基礎的控制反轉功能(選做)

第二次作業

2.1、請完成所有基于注解、自動裝配的Ioc上課示例。

2.2、請定義一個Animal動物類(名稱name,重量weight),定義兩個Animal子類貓Cat(品種type)與狗Dog(顏色color)

2.3、以Animal、Cat、Dog為基礎練習基于注解與自動裝配所有知識點,這里使用XML作為配置文件

第三次作業

3.1、請完成所有基于零配置實現Ioc上課示例。

3.3、以Animal、Cat、Dog為基礎練習基于注解、自動裝配與零配置的綜合示例,盡量貫穿所有知識點,這里不使用XML作為配置文件

十一、總結

@Compent 要求Spring容器管理,被Spring掃描,應用于不確定的功能(寬泛)
@Repository 應用于數據訪問層 DAO
@Service 應用于業務層
@Controller 應用于控制層
注解要被Spring容器管理的類 -> 配置文件指定要掃描的包 ->初始化容器,獲得bean

@Autowired 自動裝配,字段(成員變量)、方法、屬性、構造, 不支持指定名稱,配合@Qualifier
@Resource 自動裝配,指定名稱,指定類型,不屬于Spring javax
@Qualifier 在自動裝配時指定對象的名稱,避免多個不唯一的實例

@Autowired()
@Qualifier("z")
X x;

@Resource(name="z")
X x;

X
@Compent("y")
Y:X
@Compent("z")
Z:X

?

轉載于:https://www.cnblogs.com/best/p/5727935.html

總結

以上是生活随笔為你收集整理的Spring学习总结(一)——Spring实现IoC的多种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲va在线va天堂va偷拍 | 亚洲精品国产精品国自 | 天天操综合网站 | 日韩av影片在线观看 | 亚洲精品999 | 日韩精品高清视频 | 国产精品免费久久久久久久久久中文 | 狠狠色狠狠色合久久伊人 | 欧美激情视频在线免费观看 | 一二区av | 99国产在线视频 | 日韩系列在线 | 91在线资源 | 亚洲黄色av网址 | 激情欧美在线观看 | 国产精品久久久久久久久蜜臀 | 亚洲成人免费 | 亚洲免费精彩视频 | 日韩高清不卡一区二区三区 | 国产福利一区二区三区在线观看 | 精品久久久久国产免费第一页 | 日韩精品你懂的 | 亚洲精品免费观看视频 | 在线免费观看黄 | 毛片网站免费在线观看 | 在线99热 | 中文字幕一区二 | 天天草天天插 | 国产一区二区视频在线播放 | 国产xxxx性hd极品 | 精品亚洲免a | 国产999精品久久久影片官网 | 亚洲精品xxx | 国产在线 一区二区三区 | 尤物九九久久国产精品的分类 | 丁香狠狠 | 国产高清不卡在线 | 日韩在线视频线视频免费网站 | 天堂av免费观看 | a视频在线看 | 九九色综合 | 大胆欧美gogo免费视频一二区 | 97视频人人澡人人爽 | 亚洲欧美在线视频免费 | 日韩a欧美 | 高清av影院 | 精品国产资源 | 91视频在线网址 | 日韩免费二区 | 国产精品久久久久久模特 | 午夜精品电影 | 人人爽久久久噜噜噜电影 | 欧美日韩电影在线播放 | 99久久久精品 | 在线小视频你懂得 | 日韩大片免费在线观看 | 亚洲国产精品视频在线观看 | 97超碰人人澡人人爱学生 | 亚洲视频www | 久久麻豆精品 | 久久在草 | 亚洲高清在线观看视频 | 久久爱影视i | 射久久久 | 国产一级黄色电影 | 成人av视屏 | 亚洲 在线 | 18性欧美xxxⅹ性满足 | 欧美日韩中文视频 | 欧美日韩一区二区免费在线观看 | 成人h在线 | 在线观看黄污 | 欧美视频国产视频 | 色婷婷狠狠五月综合天色拍 | 免费高清在线一区 | 婷婷六月综合网 | 99久久精品免费 | 久久精品国产久精国产 | 欧美在线一级片 | 美州a亚洲一视本频v色道 | 国产一区福利在线 | 日本丰满少妇免费一区 | 96超碰在线 | av韩国在线 | 在线观看中文字幕第一页 | 国产精品黄 | 黄色www在线观看 | 日韩av影片在线观看 | 午夜色影院 | 亚洲综合色站 | 欧美狠狠操 | 18久久久久| 欧美精品久久久久a | 黄色免费网站 | 国产1区2区3区精品美女 | 国产黄色在线 | 婷婷久久综合网 | 字幕网av | 日日爱av | 欧美 日韩 国产 中文字幕 | 在线a亚洲视频播放在线观看 | 精品国产自在精品国产精野外直播 | 欧美成人精品欧美一级乱黄 | 中文字幕 欧美性 | 精品免费久久久久 | 黄色aaa毛片 | 日韩一区二区三区不卡 | 国产三级国产精品国产专区50 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 久久av高清 | 91一区二区三区久久久久国产乱 | 久久久国产一区 | 久草视频在线免费看 | 91禁看片| 欧美日韩性生活 | 国产视频2区 | 午夜精品麻豆 | 精品国产片 | 国产精品免费成人 | 欧美在线aa | 国产在线观看中文字幕 | 天天拍天天色 | 国产亚州av | 久久私人影院 | 97精品在线视频 | 国内精品久久久久影院男同志 | 欧美激情第八页 | 97视频在线观看网址 | 欧美一级日韩三级 | 国产日韩高清在线 | 五月婷婷伊人网 | 久久国色夜色精品国产 | 久久精品久久久久电影 | 国产精品美女免费视频 | 日韩av电影网站在线观看 | 日日夜夜天天操 | 国产一级视频 | 丁香午夜婷婷 | 激情综合站 | 国产专区在线看 | 97超视频在线观看 | 成人四虎影院 | 国产成人精品一区二区三区免费 | 在线免费性生活片 | 网站在线观看你们懂的 | 久久精品亚洲一区二区三区观看模式 | 国内久久 | 亚洲一级性| 91久久奴性调教 | 一区二区三区精品久久久 | 久久视频在线视频 | 永久免费av在线播放 | 91探花在线 | 伊人伊成久久人综合网小说 | 成人99免费视频 | 国产精品午夜在线 | 免费视频色 | 亚洲色视频| 日韩欧美综合在线视频 | 久久久www免费电影网 | 色综合久久天天 | 亚洲精品动漫在线 | 国产精品剧情在线亚洲 | 97av在线视频 | 免费高清在线一区 | 欧日韩在线 | 在线国产一区二区 | 国产高清99 | 五月开心六月伊人色婷婷 | 又爽又黄又无遮挡网站动态图 | 久久99久国产精品黄毛片入口 | 亚洲欧美视频在线播放 | 中文字幕在线免费播放 | 国产日韩精品一区二区 | 国产乱对白刺激视频不卡 | 国产一线在线 | 久久久男人的天堂 | 久久视频免费观看 | 亚洲 综合 精品 | 又黄又爽又无遮挡免费的网站 | 久久久这里有精品 | 亚洲自拍自偷 | 亚洲精品久久久蜜桃 | 91视频久久| 天天摸天天干天天操天天射 | 久久久www成人免费毛片麻豆 | 韩国精品福利一区二区三区 | 亚洲手机av| 亚洲 欧美变态 另类 综合 | 操处女逼| 手机在线观看国产精品 | 在线精品在线 | 日日精品 | 99久久综合国产精品二区 | 婷婷丁香激情五月 | 天天操夜夜操国产精品 | 日韩精品久久久久久久电影99爱 | 天天综合网 天天 | 欧美成年网站 | 久久 一区 | 美女久久| 五月天婷婷狠狠 | 最近日本中文字幕a | 91桃色在线观看视频 | 国产精品免费久久久久久 | www..com黄色片 | 欧美地下肉体性派对 | 欧美成年黄网站色视频 | 成人av免费在线观看 | 欧美日本在线观看视频 | 国产一卡二卡在线 | 正在播放国产91 | 中文一区在线观看 | 日韩欧美高清不卡 | 久久久 精品| 99精品99 | 国产精品久久久久久久av大片 | 三级av片| www.激情五月.com | 国色天香永久免费 | 日日夜夜人人精品 | 天天操天天射天天爱 | 国产一区二区三精品久久久无广告 | 一级片观看| 91精品在线视频观看 | 久久黄色网页 | 激情综合啪 | 国产乱对白刺激视频在线观看女王 | 国产丝袜高跟 | 国产精品6 | 免费亚洲视频在线观看 | 在线观看aaa | 中文字幕乱偷在线 | 亚洲精品乱码白浆高清久久久久久 | 狠狠地操| 免费成人av网站 | a级黄色片视频 | 欧美精品久久久久久久久久丰满 | 高清国产一区 | 一本到视频在线观看 | 精品久久一二三区 | 亚洲成av人片在线观看 | 六月丁香婷婷在线 | 精品在线视频播放 | 免费特级黄毛片 | 国产精品国产三级国产不产一地 | 久久99精品国产一区二区三区 | 国产中的精品av小宝探花 | 中文字幕一区在线 | 国产成人高清 | 久久视频精品在线 | 日本黄区免费视频观看 | 国产又粗又硬又爽视频 | 五月天激情开心 | 午夜久久影院 | 亚洲国产免费网站 | 久久国产精品久久久 | 日韩精品中文字幕在线 | 国产日韩中文字幕在线 | 日韩视频一区二区在线 | 成年人免费在线观看网站 | 国产精品成人一区二区 | 久久男人中文字幕资源站 | 欧美伊人网 | 中文字幕日韩一区二区三区不卡 | 精品一区二区在线观看 | 91成人精品国产刺激国语对白 | 国产一级在线观看 | 精品在线一区二区 | 国产在线精品一区 | 91.精品高清在线观看 | 99精品免费久久久久久久久日本 | 在线一二区 | 久久久香蕉视频 | www.超碰97.com| 天天干天天操天天干 | 91大神精品视频在线观看 | av在线免费播放网站 | 午夜精品久久久久久久99 | 91成人在线观看喷潮 | 国产精品入口传媒 | 97人人视频| 午夜久草 | 中文在线8资源库 | 欧洲精品久久久久毛片完整版 | 成人一级免费电影 | 日韩欧美69| 久久国产成人午夜av影院宅 | 98精品国产自产在线观看 | 8x成人在线 | 九九热久久免费视频 | 香蕉视频在线免费看 | 国产视频日本 | www.久久爱.cn| 国产专区视频在线观看 | 99久久er热在这里只有精品15 | 久久艹久久 | 色综合色综合久久综合频道88 | 激情综合网五月 | 这里只有精品视频在线观看 | www.av在线播放 | 久久免费黄色大片 | 国产成人黄色片 | 在线免费黄色片 | 国产精品私人影院 | 高清视频一区二区三区 | 成人h电影 | 人人射人人澡 | 摸阴视频| 欧美成人69av | 国产一区精品在线观看 | 亚洲黄色片| 国产精品久久久久久久久久免费 | 欧美在线视频二区 | 亚洲午夜久久久综合37日本 | 国产亚洲精品综合一区91 | 亚洲第一中文网 | 69av免费视频 | 亚洲美女视频在线观看 | 国产va饥渴难耐女保洁员在线观看 | 91精品国产91久久久久久三级 | 国产亚洲aⅴaaaaaa毛片 | 在线有码中文 | 天天爱天天射天天干天天 | 亚洲区精品| 免费观看9x视频网站在线观看 | 99色99| 久久96| 黄色大片日本免费大片 | 色福利网 | 99久久激情 | 成人av动漫在线观看 | 又黄又刺激的视频 | av在线收看 | a视频在线 | 精品一区中文字幕 | 涩涩成人在线 | 免费日韩电影 | 欧美日韩高清在线 | 91亚洲精品国偷拍自产在线观看 | 娇妻呻吟一区二区三区 | 国产在线欧美 | 国产精品第三页 | 国产亚洲视频中文字幕视频 | 精品福利av | av电影一区二区 | 丁香久久婷婷 | 精品在线一区二区 | 午夜丁香视频在线观看 | 天天天干天天天操 | 中文字幕在线观看不卡 | 久久久久久久免费观看 | 在线视频精品 | 日本乱码在线 | 国产亚洲欧洲 | 伊人色综合久久天天网 | 午夜影院在线观看18 | 国产精品9999久久久久仙踪林 | 91久久国产综合精品女同国语 | 免费看特级毛片 | 天天射综合网视频 | 久久久三级视频 | 99综合久久 | 在线日本看片免费人成视久网 | 超碰官网 | 日韩av高潮 | 日韩欧美在线中文字幕 | 日韩一区二区三区观看 | 日韩剧 | 我要看黄色一级片 | 亚州av网站大全 | 伊人久在线 | 成年人免费观看在线视频 | 亚洲美女视频在线观看 | 久久婷婷丁香 | 欧美日视频 | 亚洲一级片免费观看 | 亚洲精品乱码久久久久 | 免费精品在线视频 | 国产午夜精品一区二区三区 | 久久大片 | 中文字幕日本在线观看 | www.久久99| 青青草在久久免费久久免费 | 亚洲国产综合在线 | 亚洲免费一级电影 | 天天综合日日夜夜 | 国产爽视频 | 成人试看120秒 | 在线免费国产视频 | 日韩av看片| 99精品免费视频 | 中文字幕一区二区三区乱码在线 | 99久久婷婷 | 亚洲h在线播放在线观看h | 欧美精品亚州精品 | 亚洲精品xxx| 最新av观看 | 欧美日韩亚洲第一 | 精品免费视频123区 午夜久久成人 | 国产91aaa| 亚洲精品国产精品99久久 | 国产精品高 | 99九九99九九九视频精品 | 亚洲国产精品成人综合 | 欧美日韩一区二区三区视频 | 黄色一级影院 | 国产视频在线观看一区 | 精品一区二区在线看 | 日本爱爱片 | 国产高清免费av | 久久女同性恋中文字幕 | 日本精品小视频 | 色婷婷综合在线 | 天天干,天天操 | 久草精品视频在线观看 | 久久午夜电影网 | 日韩理论电影在线 | 久久精品视频在线免费观看 | 中文字幕精品一区二区三区电影 | 手机av观看 | 欧美日韩天堂 | 在线观看国产v片 | 99国产在线| 9999在线视频| avhd高清在线谜片 | av在线播放快速免费阴 | 人人草在线观看 | 欧美一级激情 | 天天草夜夜| 亚洲国产操 | 日韩电影在线观看一区二区 | 亚洲理论视频 | 欧美成人精品欧美一级乱黄 | 成人在线视频在线观看 | 精品福利视频在线观看 | 丁香婷婷激情五月 | 中文字幕丝袜一区二区 | 久久在线精品视频 | 国产亚洲精品成人av久久影院 | 蜜臀久久99精品久久久酒店新书 | 亚洲国产精品电影 | 欧美三级高清 | 日韩视频在线观看免费 | 国产成人一区二区三区影院在线 | 日韩.com| 18国产精品福利片久久婷 | www.亚洲精品在线 | 91九色精品国产 | 人人爱天天操 | 亚洲老妇xxxxxx | 国产理论片在线观看 | 中文在线字幕观看电影 | 免费在线观看午夜视频 | 成人黄色免费在线观看 | 中文字幕在线观看一区二区 | 午夜精品久久久99热福利 | 国产精品乱码久久久久 | 日本夜夜草视频网站 | 国产精品久久久免费看 | 天天草天天爽 | 精品一区二区日韩 | 九九激情视频 | 99久久综合精品五月天 | 五月婷在线观看 | 日韩在线观看中文字幕 | 国产精品video爽爽爽爽 | 808电影免费观看三年 | 久久免费视频国产 | 91看片麻豆 | 国产高清 不卡 | 亚洲视频久久久 | 亚洲开心色 | 婷婷伊人五月天 | 91久草视频| 欧美资源 | 国产一级片免费播放 | 热re99久久精品国产66热 | 久久躁日日躁aaaaxxxx | 国产精品毛片久久 | 亚洲黄色在线 | 亚洲精品婷婷 | 91麻豆视频| 91在线观看视频 | 国产一级三级 | 欧美a级在线免费观看 | 精品无人国产偷自产在线 | 在线成人看片 | 激情婷婷综合 | 超碰在线个人 | 久久夜色精品国产欧美乱 | 亚洲成人av在线播放 | www.午夜 | 欧美日韩免费在线视频 | 色综合天天 | 日韩精品一区二区三区高清免费 | 精品一二三四视频 | 日日天天av | 国产三级久久久 | 免费成人在线网站 | 久草免费福利在线观看 | 97超碰在 | 九九久久久久99精品 | 国产在线第三页 | 国外av在线 | 97视频在线观看视频免费视频 | 国产日韩在线看 | 久久福利精品 | 美女视频久久黄 | 91成人看片| 精品在线观看一区二区 | 久久久精品影视 | 国产精品久久久免费 | 激情视频在线观看网址 | 久碰视频在线观看 | 色av男人的天堂免费在线 | 波多野结衣视频网址 | 日韩69视频 | 在线亚洲精品 | 久久黄视频 | 91精品视频免费观看 | 丰满少妇在线 | 婷婷丁香自拍 | 超碰免费av | 国产精品黄色av | 免费看片网址 | 五月天久久综合网 | av一级免费| 国产美女视频免费观看的网站 | 日本最大色倩网站www | 黄色大片入口 | av观看免费在线 | 免费麻豆视频 | 亚洲色图激情文学 | 2021国产精品视频 | 日韩视频区 | 国产中文视频 | 91精品国产91久久久久福利 | 国产精品永久免费观看 | 亚洲国产精品人久久电影 | 又粗又长又大又爽又黄少妇毛片 | 中文字幕在线观看免费 | 欧美国产三区 | 永久免费的av电影 | 久久免费电影网 | 精品国产网址 | 欧洲av不卡 | 免费看污黄网站 | 精品亚洲一区二区三区 | 97超碰人| 日韩精品一区二区三区视频播放 | 一本一本久久a久久精品牛牛影视 | 成人av免费 | 国产精品系列在线观看 | 欧美精品久久久久久久亚洲调教 | 99精品在线免费在线观看 | 亚洲日本成人 | 亚洲自拍偷拍色图 | 91大神一区二区三区 | a视频免费看 | 黄色成人在线 | 国产成人在线免费观看 | 成人免费视频播放 | www色com| 一区二区高清在线 | av+在线播放在线播放 | 91成人在线观看高潮 | 亚洲天堂免费视频 | 在线免费视频一区 | 91亚洲精品久久久蜜桃 | 久久电影色| 国产精品国产三级国产不产一地 | 久久久麻豆精品一区二区 | 日韩欧美黄色网址 | 97av超碰| 欧美va日韩va | 在线视频 影院 | 操操操操网 | 在线国产高清 | 在线欧美最极品的av | 日批视频在线观看免费 | 中文字幕在线观看免费观看 | 久久69av| 国产成人不卡 | 中文字幕亚洲精品在线观看 | 日韩黄色网络 | 免费黄色a网站 | 欧美亚洲精品一区 | 国产黄色精品在线 | 久久久精品欧美一区二区免费 | 国产精品久久久av久久久 | 久久99精品国产麻豆婷婷 | 成人一区影院 | 色88久久 | 久久综合综合久久综合 | 欧美a免费 | 黄色影院在线免费观看 | 99色在线 | 黄色在线免费观看网站 | 17婷婷久久www | 精品国产自 | 久久久国产影视 | 久久在线电影 | 日韩欧美在线免费观看 | 激情五月色播五月 | 国产精品午夜久久久久久99热 | 精品一区二区免费在线观看 | 色综合网在线 | 精品国产一二三 | 美女网站在线看 | 国产精品久久久久久久久久免费看 | 日韩高清一二区 | 成人毛片100免费观看 | 探花视频在线观看免费版 | 国产成人一级电影 | 国产 亚洲 欧美 在线 | 中文字幕免费观看 | www.黄色| 色天天久久 | 99精品热视频只有精品10 | 在线观看免费色 | 亚洲精品影视在线观看 | 欧美在线观看禁18 | 在线涩涩| 日韩大片在线免费观看 | 日韩免费精品 | 久久精品欧美日韩精品 | 日韩久久精品一区二区三区下载 | 亚洲成人黄色在线 | 99久久久国产精品 | 国产免费久久精品 | 黄毛片在线观看 | 亚洲精品在线看 | 国产专区日韩专区 | 国产成年人av| 91久久丝袜国产露脸动漫 | 999成人国产| 久99久中文字幕在线 | 狠狠躁夜夜躁人人爽超碰91 | 三级黄色a| 亚洲欧洲精品一区 | 激情av网址 | 国产精品精品国产色婷婷 | 激情电影影院 | 欧美黄色免费 | 欧美色综合天天久久综合精品 | 日韩欧美在线观看一区二区 | 国产永久免费观看 | 在线看小早川怜子av | 亚洲精品国产品国语在线 | 日韩视频专区 | 日韩在线电影一区二区 | 麻豆91小视频 | 欧美一级网站 | 免费色网| 久久这里只有精品23 | 久久婷婷丁香 | 在线观看国产永久免费视频 | 亚洲精品国产欧美在线观看 | 在线免费观看羞羞视频 | 欧美日比视频 | 一级a毛片高清视频 | 亚洲国产成人久久 | 亚洲蜜桃av| 国产精品扒开做爽爽的视频 | 国产日韩精品一区二区 | 婷婷丁香色综合狠狠色 | 色偷偷97| 亚洲国产精品99久久久久久久久 | www.色国产 | 日韩大片免费在线观看 | www.久久免费 | 激情久久综合网 | 久艹视频在线免费观看 | 日韩免费视频播放 | 992tv人人草 黄色国产区 | 99视频| 国产精品久久久久久久久软件 | 精品毛片久久久久久 | 1024手机基地在线观看 | 免费的国产精品 | 97**国产露脸精品国产 | 国产一级精品绿帽视频 | 91精品国自产拍天天拍 | 欧美亚洲一区二区在线 | 精品久久久久免费极品大片 | 外国av网| 在线观看视频一区二区三区 | 成人在线观看资源 | 久久精品国产亚洲 | 伊人天天综合 | 久草精品视频在线播放 | 激情综合网天天干 | 91九色蝌蚪视频网站 | 日韩视频二区 | 一区二区三区在线免费观看 | 国产日韩精品一区二区在线观看播放 | 日韩精品一区二区三区视频播放 | 色天天中文 | 中文字幕丝袜 | 欧美精品一区二区蜜臀亚洲 | 欧美日韩国产二区 | 色亚洲网 | 国产视频二区三区 | 一区二区三区在线免费观看 | 六月婷操 | 91视频网址入口 | 久久激情小视频 | 国产精品视频地址 | 黄色国产精品 | 亚洲精品国产日韩 | 国产精品 国产精品 | 一个色综合网站 | 亚洲视频综合 | 99热精品在线观看 | 81精品国产乱码久久久久久 | 不卡视频国产 | 91影视成人 | 婷婷干五月 | 日本三级不卡 | 粉嫩高清一区二区三区 | 国产亚洲欧美在线视频 | a级国产乱理论片在线观看 特级毛片在线观看 | 九草在线视频 | av在线超碰 | 日本巨乳在线 | 亚洲.www| 欧美精品久久久久久久久久丰满 | 中文字幕视频网 | 成人av在线电影 | 国内精品久久久久久久 | 国产小视频免费在线网址 | 亚洲狠狠操 | 国产一级黄 | 日韩欧美综合在线视频 | 亚洲欧美综合精品久久成人 | 韩国av免费在线 | 在线观看韩日电影免费 | 久久一区精品 | 五月婷婷毛片 | 在线观看黄a | 久久久久久久久久久久久影院 | 色综合天天综合网国产成人网 | 国产理论片在线观看 | 狠狠色香婷婷久久亚洲精品 | 久久草精品 | 欧美在线视频免费 | 婷婷激情在线 | 亚洲 综合 国产 精品 | 一区二区三区中文字幕在线观看 | 国产一区二区三区高清播放 | 在线观看日韩免费视频 | 成人午夜网 | 91日韩精品视频 | 人人草人人草 | 亚洲欧美日韩精品久久久 | 日韩在线三区 | 亚洲午夜久久久久久久久 | 国产精品久久99精品毛片三a | 午夜aaaa | 国产精品精品久久久 | 97激情影院 | 国产福利av在线 | 国产玖玖精品视频 | 欧美色综合天天久久综合精品 | 国产色网站 | 又黄又爽又刺激视频 | 中文字幕免费不卡视频 | 国产免费a | 国产高清一级 | 一区二区视频网站 | 亚洲精品一区二区网址 | 国产成人一区二区三区在线观看 | 国产日韩精品久久 | 六月丁香在线观看 | 天堂视频中文在线 | 婷婷精品国产一区二区三区日韩 | 美女视频a美女大全免费下载蜜臀 | 国产精品美女久久久久久 | 欧美亚洲精品在线观看 | 色播五月激情五月 | 久久视频6 | 婷婷精品国产一区二区三区日韩 | 久久久久久久久久久电影 | 黄色小网站在线观看 | www操操 | 国产精品观看视频 | 九九九九九国产 | 99久久99久久综合 | 欧美日韩在线观看不卡 | 毛片一区二区 | 91在线小视频 | 91爱爱网址 | 啪嗒啪嗒免费观看完整版 | 99久久久国产精品免费99 | 亚州av一区 | 亚洲三级黄色 | 欧洲成人av| 久久经典视频 | 久久久久久久av | 91精品婷婷国产综合久久蝌蚪 | 99久久精品无码一区二区毛片 | 亚洲国产日韩欧美 | 正在播放亚洲精品 | 免费看色视频 | 精品国产一区二区三区久久久久久 | 美女视频黄免费网站 | 波多野结衣在线播放一区 | 亚洲理论电影网 | 色播五月激情综合网 | 我要看黄色一级片 | 国产理论片在线观看 | 粉嫩av一区二区三区四区在线观看 | 精品网站999www | 91在线视频网址 | 久久久久久美女 | 91色蜜桃 | 亚洲免费av观看 | 制服丝袜欧美 | 青春草免费在线视频 | 免费在线一区二区三区 | 亚洲伦理精品 | 亚洲精品动漫成人3d无尽在线 | 99精品免费久久久久久久久 | 91av在线播放| 亚洲第一久久久 | 日韩一级网站 | 国产精品久久婷婷六月丁香 | 国产在线观看午夜 | 亚洲在线网址 | 欧美精品v国产精品v日韩精品 | 伊甸园永久入口www 99热 精品在线 | 大胆欧美gogo免费视频一二区 | 精选久久 | 国产亚洲综合精品 | 免费污片 | 色婷婷狠狠五月综合天色拍 | 久草在线资源免费 | 天天干天天操天天入 | 九九九热精品 | 97精品国自产拍在线观看 | 成人午夜精品福利免费 | 婷婷av在线 | 国产在线欧美 | 亚洲成人影音 | 亚洲免费一级电影 | 夜夜骑日日操 | 亚洲成人av一区二区 | 天天操操操操操 | 亚洲综合视频在线 | 国产黄色大片 | 国产黄色免费电影 | 黄色小说视频网站 | 亚洲欧洲国产视频 | 九九热视频在线播放 | 伊人午夜视频 | 欧美日韩精品免费观看视频 | 欧美日韩高清一区二区 国产亚洲免费看 | www.五月天婷婷 | 三级av黄色 | 韩国av永久免费 | 亚洲 欧美日韩 国产 中文 | 精品久久久国产 | 亚洲欧美日韩国产一区二区三区 | 一区二区不卡视频在线观看 | 中文字幕日韩一区二区三区不卡 | 久久精品女人毛片国产 | 久久精品日产第一区二区三区乱码 | 亚洲 欧美 国产 va在线影院 | 在线播放第一页 | 久久午夜电影院 | 久久免费精品一区二区三区 | 狠狠综合| 亚洲黄色区 | 久久精品99北条麻妃 | 国产不卡在线 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 日韩精品大片 | 欧美视频网址 | 国产成人精品久久亚洲高清不卡 | 午夜美女福利 | 色狠狠狠 | 午夜电影一区 | 精品视频一区在线观看 | 黄色在线看网站 | 日本久久免费视频 | 人人看看人人 | 天天骚夜夜操 | 手机看片中文字幕 | 日韩精品中文字幕在线不卡尤物 | 97超碰在线视 | 夜夜躁日日躁狠狠久久av | 亚洲日韩中文字幕 | 色 中文字幕| 日本一区二区不卡高清 | 亚洲国产精彩中文乱码av | 成人一级片视频 | 日本久久电影网 | www天天操| 亚洲成人国产 | 日日爽夜夜爽 | 国产精品午夜在线 | 精品在线不卡 | 国产成人精品一区二区在线观看 | 婷婷综合五月 | 国产精品一区免费看8c0m | 91香蕉视频污在线 | 久久国产精品99久久久久久老狼 | 久久观看最新视频 | 久久精品资源 | 久久综合久久88 | 五月天婷婷丁香花 | 日本少妇高清做爰视频 | 欧美精品日韩 | 亚洲综合色丁香婷婷六月图片 | 久久久福利影院 | 久久中文字幕导航 | 久久成年人视频 | 国产视频在线观看一区二区 | 精品国产乱码 | 手机在线中文字幕 | 免费观看版 | 亚洲一区免费在线 | 国产日韩中文字幕 | av在线免费播放网站 | 国产国产人免费人成免费视频 | 亚洲精品视频在线免费 | 亚洲一级电影视频 | 亚洲干视频在线观看 | 91免费视频国产 | 亚洲精品2区 | 奇米网网址 | 日韩午夜电影院 | 超碰在线最新地址 | 国产999精品久久久影片官网 | 九九九九热精品免费视频点播观看 | 欧美午夜剧场 | 中文字幕色网站 | 久久精品亚洲综合专区 | 久久a国产 | 日韩免费在线视频观看 | 欧美一级欧美一级 | 国产精品1000 | 精品国产乱码久久久久久1区2匹 | 久草电影网| 久草在线费播放视频 | 久久这里精品视频 | www久久| 免费日韩视 | 成人小电影在线看 | 99re8这里有精品热视频免费 | 天天操综 | 亚洲视频在线免费看 | 精品在线二区 | 亚洲第一伊人 | 韩国av免费看 | 久久精品中文字幕一区二区三区 | 四虎影视精品永久在线观看 | 中文字幕在线国产精品 | 色老板在线 | 一区二区三区日韩视频在线观看 | 亚洲视频免费视频 | 97成人在线免费视频 | 亚洲精品在线网站 | 97成人超碰| 深夜免费小视频 | 亚洲黄色成人 | www.国产在线观看 | 欧美俄罗斯性视频 | 欧美精品在线观看一区 | 久久精品久久精品久久 | av网站免费线看精品 | 色综合久久综合中文综合网 | 精品视频久久 | 亚洲一区二区三区在线看 | 精品免费一区 | 视频99爱 | 久久久久五月天 | 天天干天天碰 | 日日草天天草 | 99久久这里有精品 | 少妇高潮流白浆在线观看 | 国产午夜精品一区二区三区 | 国产亚洲成av人片在线观看桃 | 综合激情网 | 成人网在线免费视频 | 国产精品久久久久久久免费 | 国产精品久久久久久久久久久久午夜 | 欧美日韩国产综合网 | 国产精品观看 | 色狠狠婷婷 | 超碰人在线 | 一区二区日韩av | av超碰免费在线 | 成人av影院在线观看 | 久久久久久久久久久久av | 欧美色图狠狠干 | 在线不卡的av |