Spring IOC

Spring IOC

主要內(nèi)容

Spring 框架

Spring 框架概念

? Spring 是眾多開源java項(xiàng)目中的一員,基于分層的javaEE應(yīng)用一站式輕量級(jí)開源框架靠粪,主要核心是 IOC(控制反轉(zhuǎn)/依賴注入)與 AOP(面向切面)兩大技術(shù)棒厘,實(shí)現(xiàn)項(xiàng)目在開發(fā)過程中的輕松解耦蕊蝗,提高項(xiàng)目的開發(fā)效率盯捌。

? 在項(xiàng)目中引入 Spring 立即可以帶來下面的好處 降低組件之間的耦合度,實(shí)現(xiàn)軟件各層之間的解耦寄纵”罘螅可以使用容器提供的眾多服務(wù),如:事務(wù)管理服務(wù)程拭、消息服務(wù)等等定踱。當(dāng)我們使用容器管理事務(wù)時(shí),開發(fā)人員就不再需要手工控制事務(wù).也不需處理復(fù)雜的事務(wù)傳播恃鞋。 容器提供單例模式支持崖媚,開發(fā)人員不再需要自己編寫實(shí)現(xiàn)代碼亦歉。 容器提供了AOP技術(shù),利用它很容易實(shí)現(xiàn)如權(quán)限攔截畅哑、運(yùn)行期監(jiān)控等功能肴楷。

Spring 源碼架構(gòu)

? Spring 總共大約有20個(gè)模塊,由1300多個(gè)不同的文件構(gòu)成荠呐。而這些組件被分別整合在核心容器(Core Container)赛蔫、Aop(Aspect Oriented Programming)和設(shè)備支持(Instrmentation)、數(shù)據(jù)訪問及集成(Data Access/Integeration)泥张、Web呵恢、報(bào)文發(fā)送(Messaging)、測試6個(gè)模塊集合中媚创。

核心容器:Spring-beans 和 Spring-core 模塊是 Spring 框架的核心模塊渗钉,包含控制反轉(zhuǎn)(Inversion of Control, IoC)和依賴注入(Dependency Injection, DI),核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory钞钙,工廠模式的實(shí)現(xiàn)鳄橘。BeanFactory 使用控制反轉(zhuǎn)(IOC) 思想將應(yīng)用程序的配置和依賴性規(guī)范與實(shí)際的應(yīng)用程序代碼分開。

Spring 上下文Spring Context:Spring 上下文是一個(gè)配置文件芒炼,向 Spring 框架提供上下文信息瘫怜。Spring 上下文包括企業(yè)服務(wù),例如 JNDI本刽、EJB宝磨、電子郵件、國際化盅安、校驗(yàn)和調(diào)度功能。

Spring-Expression 模塊是統(tǒng)一表達(dá)式語言(unified EL)的擴(kuò)展模塊世囊,可以查詢别瞭、管理運(yùn)行中的對(duì)象,同時(shí)也方便的可以調(diào)用對(duì)象方法株憾、操作數(shù)組蝙寨、集合等。它的語法類似于傳統(tǒng)EL嗤瞎,但提供了額外的功能墙歪,最出色的要數(shù)函數(shù)調(diào)用和簡單字符串的模板函數(shù)。

Spring-AOP:Spring-aop是Spring的另一個(gè)核心模塊, 在Spring中贝奇,他是以JVM的動(dòng)態(tài)代理技術(shù)為基礎(chǔ)虹菲,然后設(shè)計(jì)出了一系列的Aop橫切實(shí)現(xiàn),比如前置通知掉瞳、返回通知毕源、異常通知等浪漠。通過其配置管理特性,Spring AOP 模塊直接將面向切面的編程功能集成到了 Spring 框架中霎褐。所以址愿,可以很容易地使 Spring 框架管理的任何對(duì)象支持 AOP。

Spring Data Access(數(shù)據(jù)訪問):由Spring-jdbc冻璃、Spring-tx响谓、Spring-orm、Spring-jms和Spring-oxm 5個(gè)模塊組成 Spring-jdbc 模塊是 Spring 提供的JDBC抽象框架的主要實(shí)現(xiàn)模塊省艳,用于簡化 Spring JDBC娘纷。

Spring-tx 模塊是SpringJDBC事務(wù)控制實(shí)現(xiàn)模塊。使用Spring框架拍埠,它對(duì)事務(wù)做了很好的封裝失驶,通過它的Aop配置,可以靈活的配置在任何一層枣购。

Spring-Orm 模塊是ORM框架支持模塊嬉探,主要集成 hibernate, Java Persistence API (JPA) 和 Java Data Objects (JDO) 用于資源管理、數(shù)據(jù)訪問對(duì)象(DAO)的實(shí)現(xiàn)和事務(wù)策略棉圈。

Spring-Jms 模塊(Java Messaging Service)能夠發(fā)送和接受信息涩堤。

Spring-Oxm 模塊主要提供一個(gè)抽象層以支撐OXM(OXM 是 Object-to-XML-Mapping 的縮寫,它是一個(gè)O/M-mapper分瘾,將java對(duì)象映射成 XML 數(shù)據(jù)胎围,或者將 XML 數(shù)據(jù)映射成 java 對(duì)象),例如:JAXB, Castor, XMLBeans, JiBX 和 XStream 等德召。

Web 模塊:由Spring-web白魂、Spring-webmvc、Spring-websocket和Spring-webmvc-portlet 4個(gè)模塊組成上岗,Web 上下文模塊建立在應(yīng)用程序上下文模塊之上福荸,為基于 Web 的應(yīng)用程序提供了上下文。Web 模塊還簡化了處理多部分請(qǐng)求以及將請(qǐng)求參數(shù)綁定到域?qū)ο蟮墓ぷ鳌?/p>

報(bào)文發(fā)送:即Spring-messaging模塊肴掷。

Spring-messaging是Spring4 新加入的一個(gè)模塊敬锐,主要職責(zé)是為Spring 框架集成一些基礎(chǔ)的報(bào)文傳送應(yīng)用。

單元測試:即Spring-test模塊呆瞻。Spring-test模塊主要為測試提供支持

Spring 框架環(huán)境搭建

環(huán)境要求

? JDK 版本:

? JDK 1.7 及以上版本

? Spring版本:

? Spring 5.x版本

新建 Maven 項(xiàng)目

創(chuàng)建 Maven 的普通 Java 項(xiàng)目

設(shè)置項(xiàng)目的坐標(biāo)

設(shè)置項(xiàng)目的 Maven 環(huán)境

設(shè)置項(xiàng)目的名稱和存放的工作空間

調(diào)整項(xiàng)目環(huán)境

修改 JDK 版本

<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>

修改單元測試 JUnit 版本

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>

build標(biāo)簽中的pluginManagement標(biāo)簽

<!--刪除build標(biāo)簽中的pluginManagement標(biāo)簽--><build></build>

添加 Spring 框架的依賴坐標(biāo)

Maven倉庫:https://mvnrepository.com/

<!-- 添加Spring框架的核心依賴 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.4.RELEASE</version></dependency>

編寫 Bean 對(duì)象

packagecom.xxxx.service;publicclassUserService{publicvoidtest(){System.out.println("Hello Spring!");}}

添加Spring 配置文件

在項(xiàng)目的src下創(chuàng)建文件夾 resources(Alt+insert)

將 resources 標(biāo)記為資源目錄

在 src\main\resources 目錄下新建 spring.xml 文件台夺,并拷貝官網(wǎng)文檔提供的模板內(nèi)容到 xml 中。

配置 bean 到 xml 中痴脾,把對(duì)應(yīng) bean 納入到 Spring 容器來管理

spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? xmlns 即 xml namespace? xml使用的命名空間

? ? ? ? xmlns:xsi 即xml schema instance xml 遵守的具體規(guī)范

? ? ? ? xsi:schemaLocation 本文檔xml遵守的規(guī)范 官方指定

? --><beanid="userService"class="com.xxxx.service.UserService"></bean></beans>

在 spring.xml 中配置 Bean 對(duì)象

<!--

id:bean對(duì)象的id颤介,唯一標(biāo)識(shí)。一般是Bean對(duì)象的名稱的首字母小寫

class:bean對(duì)象的類路徑

--><beanid="userService"class="com.xxxx.service.UserService"></bean>

加載配置文件,獲取實(shí)例化對(duì)象

packagecom.xxxx;importcom.xxxx.service.UserService;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassApp{publicstaticvoidmain(String[]args){// 獲取Spring上下文環(huán)境 (加載配置文件)ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");// 通過getBean方法得到Spring容器中實(shí)例化好的Bean對(duì)象 (實(shí)例化Bean對(duì)象)// userService代表的是配置文件中bean標(biāo)簽的id屬性值UserService userService=(UserService)ac.getBean("userService");// 調(diào)用方法 (使用實(shí)例化對(duì)象)userService.test();}}

Spring IOC 容器 Bean 對(duì)象實(shí)例化模擬

思路:

定義Bean 工廠接口买窟,提供獲取bean方法

定義Bean工廠接口實(shí)現(xiàn)類丰泊,解析配置文件,實(shí)例化Bean對(duì)象

實(shí)現(xiàn)獲取Bean方法

定義 Bean 屬性對(duì)象

packagecom.xxxx.spring;/**

* bean對(duì)象

*? ? ? 用來接收配置文件中bean標(biāo)簽的id與class屬性值

*/publicclassMyBean{privateString id;// bean對(duì)象的id屬性值privateString clazz;// bean對(duì)象的類路徑publicMyBean(){}publicMyBean(String id,String clazz){this.id=id;this.clazz=clazz;}publicStringgetId(){returnid;}publicvoidsetId(String id){this.id=id;}publicStringgetClazz(){returnclazz;}publicvoidsetClazz(String clazz){this.clazz=clazz;}}

添加 dom4j 坐標(biāo)依賴

<!-- dom4j --><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><!-- XPath --><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version></dependency>

準(zhǔn)備自定義配置文件

spring.xml

<?xml version="1.0" encoding="utf-8" ?><beans><beanid="userService"class="com.xxxx.service.UserService"></bean><beanid="accountService"class="com.xxxx.service.AccountService"></bean></beans>

定義 Bean 工廠接口

packagecom.xxxx.spring;/**

* Bean 工廠接口定義

*/publicinterfaceMyFactory{// 通過id值獲取對(duì)象publicObjectgetBean(String id);}

定義 Bean 接口的實(shí)現(xiàn)類

packagecom.xxxx.spring;importorg.dom4j.Document;importorg.dom4j.DocumentException;importorg.dom4j.Element;importorg.dom4j.XPath;importorg.dom4j.io.SAXReader;importjava.net.URL;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;/**

* 模擬Spring的實(shí)現(xiàn)

*? 1始绍、通過構(gòu)造器得到相關(guān)配置文件

*? 2瞳购、通過dom4j解析xml文件,得到List? 存放id和class

*? 3亏推、通過反射實(shí)例化得到對(duì)象? Class.forName(類的全路徑).newInstance(); 通過Map<id,Class>存儲(chǔ)

*? 4学赛、得到指定的實(shí)例化對(duì)象

*/publicclassMyClassPathXmlApplicationContextimplementsBeanFactory{privateMap beans=newHashMap();// 實(shí)例化后的對(duì)象放入mapprivateList<MyBean>myBeans;// 存放已讀取bean 配置信息/* 1、通過構(gòu)造器得到相關(guān)配置文件 */publicMyClassPathXmlApplicationContext(String fileName){/* 2吞杭、通過dom4j解析xml文件盏浇,得到List (存放id和class) */this.parseXml(fileName);/* 3、通過反射實(shí)例化得到對(duì)象Class.forName(類路徑).newInstance();? 通過Map存儲(chǔ) */this.instanceBean();}/**

? ? * 通過dom4j解析xml文件芽狗,得到List? 存放id和class

? ? *? 1绢掰、獲取解析器

? ? *? 2、得到配置文件的URL

? ? *? 3童擎、通過解析器解析xml文件(spring.xml)

? ? *? 4滴劲、通過xpath語法,獲取beans標(biāo)簽下的所有bean標(biāo)簽

? ? *? 5顾复、通過指定語法解析文檔對(duì)象班挖,返回集合

? ? *? 6、判斷集合是否為空芯砸,遍歷集合

? ? *? 7萧芙、獲取標(biāo)簽元素中的屬性

? ? *? 8、得到Bean對(duì)象假丧,將Bean對(duì)象設(shè)置到集合中

? ? * @param fileName

? ? */privatevoidparseXml(String fileName){// 1双揪、獲取解析器SAXReader reader=newSAXReader();// 2、得到配置文件的URLURL url=this.getClass().getClassLoader().getResource(fileName);try{// 3包帚、通過解析器解析xml文件(spring.xml)Document document=reader.read(url);// 4盟榴、通過xpath語法,獲取beans標(biāo)簽下的所有bean標(biāo)簽XPath xPath=document.createXPath("beans/bean");// 通過指定語法解析文檔對(duì)象婴噩,返回集合List<Element>list=xPath.selectNodes(document);// 判斷集合是否為空,遍歷集合if(list!=null&&list.size()>0){myBeans=newArrayList<>();for(Element el:list){// 獲取標(biāo)簽元素中的屬性String id=el.attributeValue("id");// id 屬性值String clazz=el.attributeValue("class");// class 屬性值System.out.println(el.attributeValue("id"));System.out.println(el.attributeValue("class"));// 得到Bean對(duì)象MyBean bean=newMyBean(id,clazz);// 將Bean對(duì)象設(shè)置到集合中myBeans.add(bean);}}}catch(DocumentExceptione){e.printStackTrace();}}/**

? ? * 通過反射實(shí)例化得到對(duì)象?

? ? * Class.forName(類的全路徑).newInstance();?

? ? * 通過Map<id,Class>存儲(chǔ)

? ? */privatevoidinstanceBean(){// 判斷bean集合是否為空羽德,不為空遍歷得到對(duì)應(yīng)Bean對(duì)象if(myBeans!=null&&myBeans.size()>0){for(MyBean bean:myBeans){try{// 通過類的全路徑實(shí)例化對(duì)象Object object=Class.forName(bean.getClazz()).newInstance();// 將id與實(shí)例化對(duì)象設(shè)置到map對(duì)象中beans.put(bean.getId(),object);}catch(Exceptione){e.printStackTrace();}}}}/**

? ? * 通過key獲取map中的指定value

? ? * @param id

? ? * @return

? ? */@OverridepublicObjectgetBean(String id){Object object=beans.get(id);returnobject;}}

測試自定義 IOC 容器

創(chuàng)建與配置文件中對(duì)應(yīng)的Bean對(duì)象

UserService.java

packagecom.xxxx.service;publicclassUserService{publicvoidtest(){System.out.println("UserService Test...");}}

AccountService.java

packagecom.xxxx.service;publicclassAccountService{publicvoidtest(){System.out.println("AccountService Test...");}}

測試是否可以獲取實(shí)例化的Bean對(duì)象

packagecom.xxxx;importcom.xxxx.spring.MyFactory;importcom.xxxx.spring.MyClassPathXmlApplicationContext;importcom.xxxx.service.AccountService;importcom.xxxx.service.UserService;publicclassApp{publicstaticvoidmain(String[]args){MyFactory factory=newMyClassPathXmlApplicationContext("spring.xml");// 得到實(shí)例化對(duì)象UserService userService=(UserService)factory.getBean("userService");userService.test();UserService userService2=(UserService)factory.getBean("userService");System.out.println(userService+"====="+userService2);AccountService accountService=(AccountService)factory.getBean("accountService");accountService.test();}}

? Spring 容器在啟動(dòng)的時(shí)候 讀取xml配置信息几莽,并對(duì)配置的 bean 進(jìn)行實(shí)例化(這里模擬的比較簡單,僅用于幫助大家理解)宅静,同時(shí)通過上下文對(duì)象提供的 getBean() 方法拿到我們配置的 bean 對(duì)象章蚣,從而實(shí)現(xiàn)外部容器自動(dòng)化維護(hù)并創(chuàng)建 bean 的效果。

Spring IOC 配置文件加載

Spring 配置文件加載

spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userService"class="com.xxxx.service.UserService"></bean></beans>

根據(jù)相對(duì)路徑加載資源

ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");

根據(jù)絕對(duì)路徑加載資源(了解)

ApplicationContext ac=newFileSystemXmlApplicationContext("C:/IdeaWorkspace/spring01/src/main/resources/spring.xml");

Spring 多配置文件加載

? Spring 框架啟動(dòng)時(shí)可以加載多個(gè)配置文件到環(huán)境中。對(duì)于比較復(fù)雜的項(xiàng)目纤垂,可能對(duì)應(yīng)的配置文件有多個(gè)矾策,項(xiàng)目在啟動(dòng)部署時(shí)會(huì)將多個(gè)配置文件同時(shí)加載進(jìn)來。

service.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userService"class="com.xxxx.service.UserService"></bean></beans>

dao.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userDao"class="com.xxxx.dao.UserDao"></bean></beans>

可變參數(shù)峭沦,傳入多個(gè)文件名

// 同時(shí)加載多個(gè)資源文件ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml","dao.xml");

通過總的配置文件import其他配置文件

spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--導(dǎo)入需要包含的資源文件--><importresource="service.xml"/><importresource="dao.xml"/></beans>

加載時(shí)只需加載總的配置文件即可

// 加載總的資源文件ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");

Spring IOC 容器 Bean 對(duì)象實(shí)例化

構(gòu)造器實(shí)例化

注:通過默認(rèn)構(gòu)造器創(chuàng)建 空構(gòu)造方法必須存在 否則創(chuàng)建失敗

設(shè)置配置文件 spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userService"class="com.xxxx.service.UserService"></bean></beans>

獲取實(shí)例化對(duì)象

ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");UserService userService=(UserService)ac.getBean("userService");userService.test();

靜態(tài)工廠實(shí)例化(了解)

注:

要有該工廠類及工廠方法

工廠方法為靜態(tài)的

定義靜態(tài)工廠類

packagecom.xxxx.factory;importcom.xxxx.service.UserService;/**

* 定義靜態(tài)工廠類

*/publicclassStaticFactory{/**

? ? * 定義對(duì)應(yīng)的靜態(tài)方法贾虽,返回實(shí)例化對(duì)象

? ? * @return

? ? */publicstaticUserServicecreateUserService(){returnnewUserService();}}

設(shè)置配置文件 spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--靜態(tài)工廠--><beanid="userService"class="com.xxxx.factory.StaticFactory"factory-method="createUserService"></bean></beans>

獲取實(shí)例化對(duì)象

ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");UserService userService=(UserService)ac.getBean("userService");userService.test();

? 當(dāng)我們指定Spring使用靜態(tài)工廠方法來創(chuàng)建Bean實(shí)例時(shí),Spring將先解析配置文件吼鱼,并根據(jù)配置文件指定的信息蓬豁,通過反射調(diào)用靜態(tài)工廠類的靜態(tài)工廠方法,并將該靜態(tài)工廠方法的返回值作為Bean實(shí)例菇肃,在這個(gè)過程中地粪,Spring不再負(fù)責(zé)創(chuàng)建Bean實(shí)例,Bean實(shí)例是由用戶提供的靜態(tài)工廠方法提供的琐谤。

實(shí)例化工廠實(shí)例化(了解)

注:

工廠方法為非靜態(tài)方法

需要配置工廠bean蟆技,并在業(yè)務(wù)bean中配置factory-bean,factory-method屬性

定義工廠類

packagecom.xxxx.factory;importcom.xxxx.service.UserService;/**

* 定義工廠類

*/publicclassInstanceFactory{/**

? ? * 定義方法斗忌,返回實(shí)例化對(duì)象

? ? * @return

? ? */publicUserServicecreateUserService(){returnnewUserService();}}

設(shè)置配置文件 spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

實(shí)例化工廠

1.定義實(shí)例化工廠bean

? ? 2.引用工廠bean 指定工廠創(chuàng)建方法(方法為非靜態(tài))

--><beanid="instanceFactory"class="com.xxxx.factory.InstanceFactory"></bean><beanid="userService"factory-bean="instanceFactory"factory-method="createUserService"></bean></beans>

獲取實(shí)例化對(duì)象

ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");UserService userService=(UserService)ac.getBean("userService");userService.test();

Spring三種實(shí)例化Bean的方式比較

方式一:通過bean的缺省構(gòu)造函數(shù)創(chuàng)建质礼,當(dāng)各個(gè)bean的業(yè)務(wù)邏輯相互比較獨(dú)立的時(shí)候或者和外界關(guān)聯(lián)較少的時(shí)候可以使用。

方式二:利用靜態(tài)factory方法創(chuàng)建飞蹂,可以統(tǒng)一管理各個(gè)bean的創(chuàng)建几苍,如各個(gè)bean在創(chuàng)建之前需要相同的初始化處理,則可用這個(gè)factory方法險(xiǎn)進(jìn)行統(tǒng)一的處理等等陈哑。

方式三:利用實(shí)例化factory方法創(chuàng)建妻坝,即將factory方法也作為了業(yè)務(wù)bean來控制,1可用于集成其他框架的bean創(chuàng)建管理方法惊窖,2能夠使bean和factory的角色互換刽宪。

??開發(fā)中項(xiàng)目一般使用一種方式實(shí)例化bean,項(xiàng)目開發(fā)基本采用第一種方式界酒,交給Spring托管圣拄,使用時(shí)直接拿來使用即可。另外兩種了解

Spring IOC 注入

手動(dòng)實(shí)例化與外部引入

圖一:

圖二:

? 對(duì)比發(fā)現(xiàn):圖二中對(duì)于 UserDao 對(duì)象的創(chuàng)建并沒有像圖一那樣主動(dòng)的去實(shí)例化毁欣,而是通過帶參方法形式將UserDao 傳入過來庇谆,從而實(shí)現(xiàn) UserService 對(duì)UserDao類 的依賴。

??而實(shí)際創(chuàng)建對(duì)象的幕后對(duì)象即是交給了外部來創(chuàng)建凭疮。

Spring IOC 手動(dòng)裝配(注入)

? Spring 支持的注入方式共有四種:set 注入饭耳、構(gòu)造器注入、靜態(tài)工廠注入执解、實(shí)例化工廠注入寞肖。

set方法注入

注:

屬性字段需要提供set方法

四種方式,推薦使用set方法注入

業(yè)務(wù)對(duì)象 JavaBean

屬性字段提供set方法

publicclassUserService{// 業(yè)務(wù)對(duì)象UserDao set注入(提供set方法)privateUserDao userDao;publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}}

配置文件的bean標(biāo)簽設(shè)置property標(biāo)簽

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過property標(biāo)簽手動(dòng)裝配(注入):

? ? ? ? ? ? Set方法注入

? ? ? ? ? ? ? ? name:bean對(duì)象中屬性字段的名稱

? ? ? ? ? ? ? ? ref:指定bean標(biāo)簽的id屬性值

? ? --><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><beanid="userService"class="com.xxxx.service.UserService"><!--業(yè)務(wù)對(duì)象 注入--><propertyname="userDao"ref="userDao"/></bean></beans>

常用對(duì)象和基本類型

屬性字段提供set方法

publicclassUserService{// 常用對(duì)象String? set注入(提供set方法)privateString host;publicvoidsetHost(String host){this.host=host;}// 基本類型Integer? set注入(提供set方法)privateInteger port;publicvoidsetPort(Integer port){this.port=port;}}

配置文件的bean標(biāo)簽設(shè)置property標(biāo)簽

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過property標(biāo)簽手動(dòng)裝配(注入):

? ? ? ? ? ? Set方法注入

? ? ? ? ? ? ? ? name:bean對(duì)象中屬性字段的名稱

? ? ? ? ? ? ? ? value:具體的值(基本類型 常用對(duì)象|日期? 集合)

? ? --><beanid="userService"class="com.xxxx.service.UserService"><!--常用對(duì)象String 注入--><propertyname="host"value="127.0.0.1"/><!--基本類型注入--><propertyname="port"value="8080"/></bean></beans>

集合類型和屬性對(duì)象

屬性字段提供set方法

publicclassUserService{// List集合? set注入(提供set方法)publicList<String>list;publicvoidsetList(List<String>list){this.list=list;}// Set集合? set注入(提供set方法)privateSet<String>set;publicvoidsetSet(Set<String>set){this.set=set;}// Map set注入(提供set方法)privateMap<String,Object>map;publicvoidsetMap(Map<String,Object>map){this.map=map;}// Properties set注入(提供set方法)privateProperties properties;publicvoidsetProperties(Properties properties){this.properties=properties;}}

配置文件的bean標(biāo)簽設(shè)置property標(biāo)簽

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過property標(biāo)簽手動(dòng)裝配(注入):

? ? ? ? ? ? Set方法注入

? ? ? ? ? ? ? ? name:bean對(duì)象中屬性字段的名稱

? ? ? ? ? ? ? ? value:具體的值(基本類型 常用對(duì)象|日期? 集合)

? ? --><!--List集合 注入--><propertyname="list"><list><value>上海</value><value>北京</value><value>杭州</value></list></property><!--Set集合注入--><propertyname="set"><set><value>上海SH</value><value>北京BJ</value><value>杭州HZ</value></set></property><!--Map注入--><propertyname="map"><map><entry><key><value>周杰倫</value></key><value>我是如此相信</value></entry><entry><key><value>林俊杰</value></key><value>可惜沒如果</value></entry><entry><key><value>陳奕迅</value></key><value>十年</value></entry></map></property><!--Properties注入--><propertyname="properties"><props><propkey="上海">東方明珠</prop><propkey="北京">天安門</prop><propkey="杭州">西湖</prop></props></property></beans>

測試代碼

UserService.java

publicclassUserService{// 業(yè)務(wù)對(duì)象UserDao set注入(提供set方法)privateUserDao userDao;publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}// 常用對(duì)象String? set注入(提供set方法)privateString host;publicvoidsetHost(String host){this.host=host;}// 基本類型Integer? set注入(提供set方法)privateInteger port;publicvoidsetPort(Integer port){this.port=port;}// List集合? set注入(提供set方法)publicList<String>list;publicvoidsetList(List<String>list){this.list=list;}// List集合輸出publicvoidprintList(){list.forEach(s->System.out.println(s));}// Set集合? set注入(提供set方法)privateSet<String>set;publicvoidsetSet(Set<String>set){this.set=set;}// Set集合輸出publicvoidprintSet(){set.forEach(s->System.out.println(s));}// Map set注入(提供set方法)privateMap<String,Object>map;publicvoidsetMap(Map<String,Object>map){this.map=map;}// Map輸出publicvoidprintMap(){map.forEach((k,v)->System.out.println(k+","+v));}// Properties set注入(提供set方法)privateProperties properties;publicvoidsetProperties(Properties properties){this.properties=properties;}// Properties輸出publicvoidprintProperties(){properties.forEach((k,v)->System.out.println(k+"新蟆,"+v));}publicvoidtest(){System.out.println("UserService Test...");userDao.test();studentDao.test();System.out.println("Host:"+host+"觅赊,port:"+port);// List集合printList();// Set集合printSet();// MapprintMap();// PropertiesprintProperties();}}

spring.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過property標(biāo)簽手動(dòng)裝配(注入):

? ? ? ? ? ? Set方法注入

? ? ? ? ? ? ? ? name:bean對(duì)象中屬性字段的名稱

? ? ? ? ? ? ? ? ref:指定bean標(biāo)簽的id屬性值

? ? ? ? ? ? ? ? value:具體的值(基本類型 常用對(duì)象|日期? 集合)

? ? --><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><beanid="userService"class="com.xxxx.service.UserService"><!--業(yè)務(wù)對(duì)象 注入--><propertyname="userDao"ref="userDao"/><propertyname="studentDao"ref="studentDao"/><!--常用對(duì)象String 注入--><propertyname="host"value="192.168.1.109"/><!--基本類型注入--><propertyname="port"value="8080"/><!--List集合 注入--><propertyname="list"><list><value>上海</value><value>北京</value><value>杭州</value></list></property><!--Set集合注入--><propertyname="set"><set><value>上海SH</value><value>北京BJ</value><value>杭州HZ</value></set></property><!--Map注入--><propertyname="map"><map><entry><key><value>周杰倫</value></key><value>我是如此相信</value></entry><entry><key><value>林俊杰</value></key><value>可惜沒如果</value></entry><entry><key><value>陳奕迅</value></key><value>十年</value></entry></map></property><!--Properties注入--><propertyname="properties"><props><propkey="上海">東方明珠</prop><propkey="北京">天安門</prop><propkey="杭州">西湖</prop></props></property></bean></beans>

構(gòu)造器注入

注:

提供帶參構(gòu)造器

單個(gè)Bean對(duì)象作為參數(shù)

Java 代碼

publicclassUserService{privateUserDao userDao;// JavaBean 對(duì)象publicUserService(UserDao userDao){this.userDao=userDao;}publicvoidtest(){System.out.println("UserService Test...");userDao.test();}}

XML配置

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過構(gòu)造器注入:

? ? ? ? ? ? 通過constructor-arg標(biāo)簽進(jìn)行注入

? ? ? ? ? ? ? ? name:屬性名稱

? ? ? ? ? ? ? ? ref:指定bean標(biāo)簽的id屬性值

? ? --><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><beanid="userService"class="com.xxxx.service.UserService"><constructor-argname="userDao"ref="userDao"></constructor-arg></bean></beans>

多個(gè)Bean對(duì)象作為參數(shù)

Java 代碼

publicclassUserService{privateUserDao userDao;// JavaBean 對(duì)象privateAccountDao accountDao// JavaBean 對(duì)象publicUserService(UserDao userDao,AccountDao accountDao){this.userDao=userDao;this.accountDao=accountDao;}publicvoidtest(){System.out.println("UserService Test...");userDao.test();accountDao.test();}}

XML配置

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過構(gòu)造器注入:

? ? ? ? ? ? 通過constructor-arg標(biāo)簽進(jìn)行注入

? ? ? ? ? ? ? ? name:屬性名稱

? ? ? ? ? ? ? ? ref:指定bean標(biāo)簽的id屬性值

? ? --><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><beanid="accountDao"class="com.xxxx.dao.AccountDao"></bean><beanid="userService"class="com.xxxx.service.UserService"><constructor-argname="userDao"ref="userDao"></constructor-arg><constructor-argname="accountDao"ref="accountDao"></constructor-arg></bean></beans>

Bean對(duì)象和常用對(duì)象作為參數(shù)

Java 代碼

publicclassUserService{privateUserDao userDao;// JavaBean 對(duì)象privateAccountDao accountDao;// JavaBean 對(duì)象privateString uname;// 字符串類型publicUserService(UserDao userDao,AccountDao accountDao,String uname){this.userDao=userDao;this.accountDao=accountDao;this.uname=uname;}publicvoidtest(){System.out.println("UserService Test...");userDao.test();accountDao.test();System.out.println("uname:"+uname);}}

XML配置

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><!--

? ? ? ? IOC通過構(gòu)造器注入:

? ? ? ? ? ? 通過constructor-arg標(biāo)簽進(jìn)行注入

? ? ? ? ? ? ? ? name:屬性名稱

? ? ? ? ? ? ? ? ref:指定bean標(biāo)簽的id屬性值

value:基本類型 常用對(duì)象的值

? ? ? ? ? ? ? ? index:構(gòu)造器中參數(shù)的下標(biāo),從0開始

? ? --><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><beanid="accountDao"class="com.xxxx.dao.AccountDao"></bean><beanid="userService"class="com.xxxx.service.UserService"><constructor-argname="userDao"ref="userDao"></constructor-arg><constructor-argname="accountDao"ref="accountDao"></constructor-arg><constructor-argname="uname"value="admin"></constructor-arg></bean></beans>

循環(huán)依賴問題

循環(huán)問題產(chǎn)生的原因:

? Bean通過構(gòu)造器注入琼稻,之間彼此相互依賴對(duì)方導(dǎo)致bean無法實(shí)例化吮螺。

問題展示:

Java 代碼

publicclassAccountService{privateRoleService roleService;publicAccountService(RoleService roleService){this.roleService=roleService;}publicvoidtest(){System.out.println("AccountService Test...");}}publicclassRoleService{privateAccountService accountService;publicRoleService(AccountService accountService){this.accountService=accountService;}publicvoidtest(){System.out.println("RoleService Test...");}}

XML配置

<!--

? ? 如果多個(gè)bean對(duì)象中互相注入,則會(huì)出現(xiàn)循環(huán)依賴的問題

? ? 可以通過set方法注入解決

--><beanid="accountService"class="com.xxxx.service.AccountService"><constructor-argname="roleService"ref="roleService"/></bean><beanid="roleService"class="com.xxxx.service.RoleService"><constructor-argname="accountService"ref="accountService"/></bean>

如何解決:將構(gòu)造器注入改為set方法注入

Java代碼

publicclassAccountService{privateRoleService roleService;/* public AccountService(RoleService roleService) {

? ? ? ? this.roleService = roleService;

? ? }*/publicvoidsetRoleService(RoleService roleService){this.roleService=roleService;}publicvoidtest(){System.out.println("AccountService Test...");}}publicclassRoleService{privateAccountService accountService;/* public RoleService(AccountService accountService) {

? ? ? ? this.accountService = accountService;

? ? }*/publicvoidsetAccountService(AccountService accountService){this.accountService=accountService;}publicvoidtest(){System.out.println("RoleService Test...");}}

XML配置

<!--

<bean id="accountService" class="com.xxxx.service.AccountService">

? ? <constructor-arg name="roleService" ref="roleService"/>

? ? </bean>

? ? <bean id="roleService" class="com.xxxx.service.RoleService">

? ? ? ? <constructor-arg name="accountService" ref="accountService"/>

? ? </bean>

--><!--修改為set方法注入--><beanid="accountService"class="com.xxxx.service.AccountService"><propertyname="roleService"ref="roleService"/></bean><beanid="roleService"class="com.xxxx.service.RoleService"><propertyname="accountService"ref="accountService"/></bean>

靜態(tài)工廠注入

定義靜態(tài)工廠類

publicclassStaticFactory{// 定義靜態(tài)方法publicstaticTypeDaocreateTypeDao(){returnnewTypeDao();}}

Java代碼

publicclassTypeService{privateTypeDao typeDao;publicvoidsetTypeDao(TypeDao typeDao){this.typeDao=typeDao;}publicvoidtest(){System.out.println("TypeService Test...");}}

XML配置

在配置文件中設(shè)置bean標(biāo)簽欣簇,指定工廠對(duì)象并設(shè)置對(duì)應(yīng)的方法

<beanid="typeService"class="com.xxxx.service.TypeService"><propertyname="typeDao"ref="typeDao"/></bean><!--

靜態(tài)工廠注入:

靜態(tài)工廠注入也是借助set方法注入规脸,只是被注入的bean對(duì)象的實(shí)例化是通過靜態(tài)工廠實(shí)例化的

--><beanid="typeDao"class="com.xxxx.factory.StaticFactory"factory-method="createTypeDao"></bean>

實(shí)例化工廠注入

定義工廠類

publicclassInstanceFactory{publicTypeDaocreateTypeDao(){returnnewTypeDao();}}

Java代碼

publicclassTypeService{privateTypeDao typeDao;publicvoidsetTypeDao(TypeDao typeDao){this.typeDao=typeDao;}publicvoidtest(){System.out.println("TypeService Test...");}}

XML配置

聲明工廠bean標(biāo)簽,聲明bean對(duì)象熊咽,指明工廠對(duì)象和工廠方法

<beanid="typeService"class="com.xxxx.service.TypeService"><propertyname="typeDao"ref="typeDao"/></bean><!--

實(shí)例化工廠注入:

實(shí)例化工廠注入也是借助set方法注入莫鸭,只是被注入的bean對(duì)象的實(shí)例化是通過實(shí)例化工廠實(shí)例化的

--><beanid="instanceFactory"class="com.xxxx.factory.InstanceFactory"></bean><beanid="typeDao"factory-bean="instanceFactory"factory-method="createTypeDao"></bean>

重點(diǎn)掌握set注入和構(gòu)造器注入,工廠方式了解即可横殴。實(shí)際開發(fā)中基本使用set方式注入bean被因。

注入方式的選擇

??開發(fā)項(xiàng)目中set方式注入首選

? 使用構(gòu)造注入可以在構(gòu)建對(duì)象的同時(shí)一并完成依賴關(guān)系的建立,對(duì)象一建立則所有的一切也就準(zhǔn)備好了衫仑,但如果要建立的對(duì)象關(guān)系很多梨与,使用構(gòu)造器注入會(huì)在構(gòu)建函數(shù)上留下一長串的參數(shù),且不易記憶,這時(shí)使用Set注入會(huì)是個(gè)不錯(cuò)的選擇。

使用Set注入可以有明確的名稱文狱,可以了解注入的對(duì)象會(huì)是什么粥鞋,像setXXX()這樣的名稱會(huì)比記憶Constructor上某個(gè)參數(shù)的位置代表某個(gè)對(duì)象更好。

p名稱空間的使用

? spring2.5以后瞄崇,為了簡化setter方法屬性注入呻粹,引用p名稱空間的概念,可以將 子元素苏研,簡化為元素屬性配置等浊。

屬性字段提供 set 方法

publicclassUserService{// 業(yè)務(wù)對(duì)象UserDao set注入(提供set方法)privateUserDao userDao;publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}// 常用對(duì)象String? set注入(提供set方法)privateString host;publicvoidsetHost(String host){this.host=host;}}

在配置文件 spring.xml 引入 p 名稱空間

xmlns:p="http://www.springframework.org/schema/p"

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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/beans? ? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><!--

p:屬性名:="xxx" 引入常量值

p:屬性名-ref:="xxx" 引入其他Bean對(duì)象的id屬性值

--><beanid="userService"class="com.xxxx.service.UserService"p:userDao-ref="userDao"p:host="127.0.0.1"/></beans>

Spring IOC 自動(dòng)裝配(注入)

注解方式注入 Bean

? 對(duì)于 bean 的注入,除了使用 xml 配置以外摹蘑,可以使用注解配置筹燕。注解的配置,可以簡化配置文件衅鹿,提高開發(fā)的速度撒踪,使程序看上去更簡潔。對(duì)于注解的解釋大渤,Spring對(duì)于注解有專門的解釋器制妄,對(duì)定義的注解進(jìn)行解析,實(shí)現(xiàn)對(duì)應(yīng)bean對(duì)象的注入兼犯。通過反射技術(shù)實(shí)現(xiàn)

準(zhǔn)備環(huán)境

修改配置文件

<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd? ? ? http://www.springframework.org/schema/context? ? ? http://www.springframework.org/schema/context/spring-context.xsd">

開啟自動(dòng)化注入

<!--開啟自動(dòng)化裝配(注入)--><context:annotation-config/><beanid="userDao"class="com.xxxx.dao.UserDao"></bean><beanid="userService"class="com.xxxx.service.UserService"></bean>

給注入的bean對(duì)象添加注解

@Resource注解

@Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

默認(rèn)根據(jù)屬性字段名稱查找對(duì)應(yīng)的bean對(duì)象 (屬性字段的名稱與bean標(biāo)簽的id屬性值相等)

如果屬性字段名稱未找到,則會(huì)通過類型(Class類型)查找

屬性可以提供set方法切黔,也可以不提供set方法

注解可以聲明在屬性級(jí)別 或 set方法級(jí)別

可以設(shè)置name屬性砸脊,name屬性值必須與bean標(biāo)簽的id屬性值一致;如果設(shè)置了name屬性值纬霞,就只會(huì)按照name屬性值查找bean對(duì)象

當(dāng)注入接口時(shí)凌埂,如果接口只有一個(gè)實(shí)現(xiàn)則正常實(shí)例化;如果接口存在多個(gè)實(shí)現(xiàn)诗芜,則需要使用name屬性指定需要被實(shí)例化的bean對(duì)象

代碼示例

默認(rèn)根據(jù)屬性字段名稱查找對(duì)應(yīng)的bean對(duì)象 (屬性字段的名稱與bean標(biāo)簽的id屬性值相等)

/**

* @Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

*? 默認(rèn)根據(jù)屬性字段名稱查找對(duì)應(yīng)的bean對(duì)象 (屬性字段的名稱與bean標(biāo)簽的id屬性值相等)

*/publicclassUserService{@ResourceprivateUserDao userDao;// 屬性字段的名稱與bean標(biāo)簽的id屬性值相等publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}publicvoidtest(){// 調(diào)用UserDao的方法userDao.test();}}

如果屬性字段名稱未找到瞳抓,則會(huì)通過類型(Class類型)查找

/**

* @Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

*? 如果屬性字段名稱未找到,則會(huì)通過類型(Class類型)查找

*/publicclassUserService{@ResourceprivateUserDao ud;// 當(dāng)在配置文件中屬性字段名(ud)未找到伏恐,則會(huì)查找對(duì)應(yīng)的class(UserDao類型)publicvoidsetUd(UserDao ud){this.ud=ud;}publicvoidtest(){// 調(diào)用UserDao的方法ud.test();}}

屬性可以提供set方法孩哑,也可以不提供set方法

/**

* @Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

*? 屬性可以提供set方法,也可以不提供set方法

*/publicclassUserService{@ResourceprivateUserDao userDao;// 不提供set方法publicvoidtest(){// 調(diào)用UserDao的方法userDao.test();}}

注解可以聲明在屬性級(jí)別 或 set方法級(jí)別

/**

* @Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

*? 注解可以聲明在屬性級(jí)別 或 set方法級(jí)別

*/publicclassUserService{privateUserDao userDao;@Resource// 注解也可設(shè)置在set方法上publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}publicvoidtest(){// 調(diào)用UserDao的方法userDao.test();}}

可以設(shè)置name屬性翠桦,name屬性值必須與bean標(biāo)簽的id屬性值一致横蜒;如果設(shè)置了name屬性值,就只會(huì)按照name屬性值查找bean對(duì)象

/**

* @Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

*? 可以設(shè)置name屬性销凑,name屬性值必須與bean的id屬性值一致丛晌;

*? 如果設(shè)置了name屬性值,就只會(huì)按照name屬性值查找bean對(duì)象

*/publicclassUserService{@Resource(name="userDao")// name屬性值與配置文件中bean標(biāo)簽的id屬性值一致privateUserDao ud;publicvoidtest(){// 調(diào)用UserDao的方法ud.test();}}

當(dāng)注入接口時(shí)斗幼,如果接口只有一個(gè)實(shí)現(xiàn)則正常實(shí)例化澎蛛;如果接口存在多個(gè)實(shí)現(xiàn),則需要使用name屬性指定需要被實(shí)例化的bean對(duì)象

定義接口類 IUserDao.java

packagecom.xxxx.dao;/**

* 定義接口類

*/publicinterfaceIUserDao{publicvoidtest();}

定義接口實(shí)現(xiàn)類 UserDao01.java

packagecom.xxxx.dao;/**

* 接口實(shí)現(xiàn)類

*/publicclassUserDao01implementsIUserDao{@Overridepublicvoidtest(){System.out.println("UserDao01...");}}

定義接口實(shí)現(xiàn)類 UserDao02.java

packagecom.xxxx.dao;/**

* 接口實(shí)現(xiàn)類

*/publicclassUserDao02implementsIUserDao{@Overridepublicvoidtest(){System.out.println("UserDao02...");}}

XML配置文件

<!--開啟自動(dòng)化裝配(注入)--><context:annotation-config/><beanid="userService"class="com.xxxx.service.UserService"></bean><beanid="userDao01"class="com.xxxx.dao.UserDao01"></bean><beanid="userDao02"class="com.xxxx.dao.UserDao01"></bean>

使用注解 UserService.java

/**

* @Resource注解實(shí)現(xiàn)自動(dòng)注入(反射)

*? 當(dāng)注入接口時(shí)蜕窿,如果接口只有一個(gè)實(shí)現(xiàn)則正常實(shí)例化谋逻;如果接口存在多個(gè)實(shí)現(xiàn),則需要使用name屬性指定需要被實(shí)例化的bean對(duì)象

*/publicclassUserService{@Resource(name="userDao01")// name屬性值與其中一個(gè)實(shí)現(xiàn)類的bean標(biāo)簽的id屬性值一致privateIUserDao iUserDao;// 注入接口(接口存在多個(gè)實(shí)現(xiàn))publicvoidtest(){iUserDao.test();}}

@Autowired注解

@Autowired注解實(shí)現(xiàn)自動(dòng)化注入:

默認(rèn)通過類型(Class類型)查找bean對(duì)象 與屬性字段的名稱無關(guān)

屬性可以提供set方法渠羞,也可以不提供set方法

注解可以聲明在屬性級(jí)別 或 set方法級(jí)別

可以添加@Qualifier結(jié)合使用斤贰,通過value屬性值查找bean對(duì)象(value屬性值必須要設(shè)置,且值要與bean標(biāo)簽的id屬性值對(duì)應(yīng))

默認(rèn)通過類型(Class類型)查找bean對(duì)象 與屬性字段的名稱無關(guān)

/**

* @Autowired注解實(shí)現(xiàn)自動(dòng)化注入

*? 默認(rèn)通過類型(Class類型)查找bean對(duì)象? 與屬性字段的名稱無關(guān)

*/publicclassUserService{@AutowiredprivateUserDao userDao;// 默認(rèn)通過類型(Class類型)查找bean對(duì)象? 與屬性字段的名稱無關(guān)publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}publicvoidtest(){// 調(diào)用UserDao的方法userDao.test();}}

屬性可以提供set方法次询,也可以不提供set方法

/**

* @Autowired注解實(shí)現(xiàn)自動(dòng)化注入

*? 屬性可以提供set方法荧恍,也可以不提供set方法

*/publicclassUserService{@AutowiredprivateUserDao userDao;// 不提供set方法publicvoidtest(){// 調(diào)用UserDao的方法userDao.test();}}

注解可以聲明在屬性級(jí)別 或 set方法級(jí)別

/**

* @Autowired注解實(shí)現(xiàn)自動(dòng)化注入

*? 注解可以聲明在屬性級(jí)別 或 set方法級(jí)別

*/publicclassUserService{privateUserDao userDao;@Autowired// 注解可以聲明在set方法級(jí)別publicvoidsetUserDao(UserDao userDao){this.userDao=userDao;}publicvoidtest(){// 調(diào)用UserDao的方法userDao.test();}}

可以添加@Qualifier結(jié)合使用,通過value屬性值查找bean對(duì)象(value屬性值必須要設(shè)置屯吊,且值要與bean標(biāo)簽的id屬性值對(duì)應(yīng))

/**

* @Autowired注解實(shí)現(xiàn)自動(dòng)化注入

*? 可以添加@Qualifier結(jié)合使用送巡,通過value屬性值查找bean對(duì)象

value屬性值必須要設(shè)置,且值要與bean標(biāo)簽的id屬性值對(duì)應(yīng)

*/publicclassUserService{@Autowired@Qualifier(value="userDao")// value屬性值必須要設(shè)置盒卸,且值要與bean標(biāo)簽的id屬性值對(duì)應(yīng)privateUserDao userDao;publicvoidtest(){userDao.test();}}

推薦使用**@Resource** 注解是屬于J2EE的骗爆,減少了與Spring的耦合。

Spring IOC 掃描器

? 實(shí)際的開發(fā)中蔽介,bean的數(shù)量非常多摘投,采用手動(dòng)配置bean的方式已無法滿足生產(chǎn)需要煮寡,Spring這時(shí)候同樣提供了掃描的方式,對(duì)掃描到的bean對(duì)象統(tǒng)一進(jìn)行管理犀呼,簡化開發(fā)配置幸撕,提高開發(fā)效率。

Spring IOC 掃描器的配置

Spring IOC 掃描器

? 作用:bean對(duì)象統(tǒng)一進(jìn)行管理外臂,簡化開發(fā)配置坐儿,提高開發(fā)效率

? 1、設(shè)置自動(dòng)化掃描的范圍

? ? ? ? ? ? 如果bean對(duì)象未在指定包范圍宋光,即使聲明了注解貌矿,也無法實(shí)例化

? 2、使用指定的注解(聲明在類級(jí)別)? ? bean對(duì)象的id屬性默認(rèn)是 類的首字母小寫

? ? ? ? Dao層:

? ? ? ? ? ? @Repository

? ? ? ? Service層:

? ? ? ? ? ? @Service

? ? ? ? Controller層:

? ? ? ? ? ? @Controller

? ? ? ? 任意類:

? ? ? ? ? ? @Component

? ? 注:開發(fā)過程中建議按照指定規(guī)則聲明注解

設(shè)置自動(dòng)化掃描范圍

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans? ? ? https://www.springframework.org/schema/beans/spring-beans.xsd? ? ? http://www.springframework.org/schema/context? ? ? http://www.springframework.org/schema/context/spring-context.xsd"><!-- 設(shè)置自動(dòng)化掃描的范圍 --><context:component-scanbase-package="com.xxxx"/></beans>

使用特定的注解

@Repository (Dao層)

@RepositorypublicclassResourceDao{publicvoidtest(){System.out.println("ResourceDao...");}}

@Service(Service層 )

@ServicepublicclassResourceService{@ResourceprivateResourceDao resourceDao;// service層注入dao層的bean對(duì)象publicvoidtest(){System.out.println("ResourceService...");resourceDao.test();}}

@Controller (Controller 層 )

@ControllerpublicclassResourceController{@AutowiredprivateResourceService resourceService;// Controller層注入service層的bean對(duì)象publicvoidtest(){System.out.println("ResourceController...");resourceService.test();}}

@Component (任意層)

@ComponentpublicclassPropertyUtils{publicvoidtest(){System.out.println("PropertyUtils...");}}

Spring 模擬用戶登錄流程

Dao層 (查詢用戶記錄)

定義JavaBean User.java

packagecom.xxxx.po;/**

* User 用戶實(shí)體類

*/publicclassUser{privateString userName;// 用戶名稱privateString userPwd;// 用戶密碼publicStringgetUserName(){returnuserName;}publicvoidsetUserName(String userName){this.userName=userName;}publicStringgetUserPwd(){returnuserPwd;}publicvoidsetUserPwd(String userPwd){this.userPwd=userPwd;}}

編寫Dao層 UserDao.java

packagecom.xxxx.dao;importcom.xxxx.po.User;importorg.springframework.stereotype.Repository;@RepositorypublicclassUserDao{privatefinalString USERNAME="admin";privatefinalString USERPWD="admin";/**

? ? * 通過用戶名稱查詢用戶對(duì)象

? ? * @param userName

? ? * @return

? ? */publicUserqueryUserByUserName(String userName){User user=null;// 判斷用戶名稱是否正確if(!USERNAME.equals(userName)){// 如果不正確罪佳,返回nullreturnnull;}// 如果正確逛漫,將用戶名稱和密碼設(shè)置到user對(duì)象中user=newUser();user.setUserName(USERNAME);user.setUserPwd(USERPWD);returnuser;}}

Service層 (業(yè)務(wù)邏輯處理)

定義業(yè)務(wù)處理返回消息模型 MessageModel.java

packagecom.xxxx.po.vo;/**

* 定義業(yè)務(wù)處理返回消息模型

*? ? 封裝返回結(jié)果

*/publicclassMessageModel{privateInteger resultCode=1;// 結(jié)果狀態(tài)碼? 1=成功,0=失敗privateString resultMsg="操作成功菇民!";// 結(jié)果提示信息publicIntegergetResultCode(){returnresultCode;}publicvoidsetResultCode(Integer resultCode){this.resultCode=resultCode;}publicStringgetResultMsg(){returnresultMsg;}publicvoidsetResultMsg(String resultMsg){this.resultMsg=resultMsg;}}

編寫Service層 UserService.java

packagecom.xxxx.service;importcom.xxxx.dao.UserDao1;importcom.xxxx.po.User;importcom.xxxx.po.vo.MessageModel;importorg.springframework.stereotype.Service;importjavax.annotation.Resource;@ServicepublicclassUserService{@ResourceprivateUserDao userDao;/**

? ? * 驗(yàn)證用戶登錄

? ? * @param userName

? ? * @param userPwd

? ? * @return

? ? */publicMessageModeluserLoginCheck(String userName,String userPwd){// 定義業(yè)務(wù)處理返回消息模型MessageModel messageModel=newMessageModel();// 判斷用戶名稱是否非空if(null==userName||"".equals(userName.trim())){messageModel.setResultCode(0);messageModel.setResultMsg("用戶名不能為空尽楔!");returnmessageModel;}// 判斷用戶密碼是否為空if(null==userPwd||"".equals(userPwd.trim())){messageModel.setResultCode(0);messageModel.setResultMsg("密碼不能為空!");returnmessageModel;}// 通過用戶名稱查詢用戶對(duì)象User user=userDao.queryUserByUserName(userName);// 判斷用戶對(duì)象是否為空if(null==user){messageModel.setResultCode(0);messageModel.setResultMsg("該用戶不存在第练!");returnmessageModel;}// 如果用戶對(duì)象不為空阔馋,判斷密碼是否正確if(!user.getUserPwd().equals(userPwd)){messageModel.setResultCode(0);messageModel.setResultMsg("用戶密碼不正確!");returnmessageModel;}// 登錄成功messageModel.setResultMsg("登錄成功娇掏!");returnmessageModel;}}

Controller層 (接收請(qǐng)求)

編寫Controller層 UserController.java

packagecom.xxxx.controller;importcom.xxxx.po.vo.MessageModel;importcom.xxxx.service.UserService1;importorg.springframework.stereotype.Controller;importjavax.annotation.Resource;@ControllerpublicclassUserController{@ResourceprivateUserService userService;/**

? ? * 用戶登錄

? ? * @param userName

? ? * @param userPwd

? ? * @return

? ? */publicMessageModellogin(String userName,String userPwd){// 調(diào)用Dao層判斷用戶登錄操作呕寝,返回結(jié)果MessageModel messageModel=userService.userLoginCheck(userName,userPwd);returnmessageModel;}}

通過 JUnit 進(jìn)行測試

packagecom.xxxx;importcom.xxxx.controller.UserController;importcom.xxxx.po.vo.MessageModel;importorg.junit.Test;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassTestLogin{@Testpublicvoidtest(){// 得到Spring容器上下文環(huán)境ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");// 得到UserController實(shí)例化對(duì)象UserController userController=(UserController)ac.getBean("userController");// 傳入?yún)?shù)調(diào)用UserController的方法,返回封裝類MessageModel messageModel=userController.login("admin","admin");System.out.println("狀態(tài)碼:"+messageModel.getResultCode()+"婴梧,提示信息:"+messageModel.getResultMsg());}}

Bean的作用域與生命周期

Bean的作用域

? 默認(rèn)情況下下梢,我們從Spring容器中拿到的對(duì)象均是單例的,對(duì)于bean的作用域類型如下:

singleton 作用域

??注意: lazy-init是懶加載, 如果等于true時(shí)作用是指Spring容器啟動(dòng)的時(shí)候不會(huì)去實(shí)例化這個(gè)bean, 而是在程序調(diào)用時(shí)才去實(shí)例化. 默認(rèn)是false即Spring容器啟動(dòng)時(shí)實(shí)例化.

? 默認(rèn)情況下塞蹭,被管理的bean只會(huì)IOC容器中存在一個(gè)實(shí)例孽江,對(duì)于所有獲取該Bean的操作Spring容器將只返回同一個(gè)Bean。

??容器在啟動(dòng)的情況下就實(shí)例化所有singleton 的 bean對(duì)象番电,并緩存與容器中

lazy-init屬性(懶加載)

如果為false岗屏,則在IOC容器啟動(dòng)時(shí)會(huì)實(shí)例化bean對(duì)象永丝,默認(rèn)false

? 如果為true误续,則IOC容器啟動(dòng)時(shí)不會(huì)實(shí)例化Bean對(duì)象,在使用bean對(duì)象時(shí)才會(huì)實(shí)例化

lazy-init設(shè)置為false有什么好處鼻弧?

? 1)可以提前發(fā)現(xiàn)潛在的配置問題

? 2)Bean 對(duì)象存在于緩存中娩井,使用時(shí)不用再去實(shí)例化bean暇屋,加快程序運(yùn)行效率

什么對(duì)象適合作為單例對(duì)象?

? 一般來說對(duì)于無狀態(tài)或狀態(tài)不可改變的對(duì)象適合使用單例模式洞辣。(不存在會(huì)改變對(duì)象狀態(tài)的成員變量)

? 比如:controller層咐刨、service層昙衅、dao層

什么是無狀態(tài)或狀態(tài)不可改變的對(duì)象?

? 實(shí)際上對(duì)象狀態(tài)的變化往往均是由于屬性值得變化而引起的定鸟,比如user類 姓名屬性會(huì)有變化绒尊,屬性姓名的變化一般會(huì)引起user對(duì)象狀態(tài)的變化。對(duì)于我們的程序來說仔粥,無狀態(tài)對(duì)象沒有實(shí)例變量的存在,保證了線程的安全性蟹但,service 層業(yè)務(wù)對(duì)象即是無狀態(tài)對(duì)象躯泰。線程安全的。

prototype 作用域

? 通過scope=“prototype” 設(shè)置bean的類型 华糖,每次向Spring容器請(qǐng)求獲取Bean都返回一個(gè)全新的Bean麦向,相對(duì)于"singleton"來說就是不緩存Bean,每次都是一個(gè)根據(jù)Bean定義創(chuàng)建的全新Bean客叉。

Web應(yīng)用中的作用域

request作用域

表示每個(gè)請(qǐng)求需要容器創(chuàng)建一個(gè)全新Bean诵竭。比如提交表單的數(shù)據(jù)必須是對(duì)每次請(qǐng)求新建一個(gè)Bean來保持這些表單數(shù)據(jù),請(qǐng)求結(jié)束釋放這些數(shù)據(jù)兼搏。

session作用域

表示每個(gè)會(huì)話需要容器創(chuàng)建一個(gè)全新Bean卵慰。比如對(duì)于每個(gè)用戶一般會(huì)有一個(gè)會(huì)話,該用戶的用戶信息需要存儲(chǔ)到會(huì)話中佛呻,此時(shí)可以將該Bean作用域配置為session級(jí)別裳朋。

globalSession作用域

類似于session作用域,其用于portlet(Portlet是基于Java的Web組件吓著,由Portlet容器管理鲤嫡,并由容器處理請(qǐng)求,生產(chǎn)動(dòng)態(tài)內(nèi)容)環(huán)境的web應(yīng)用绑莺。如果在非portlet環(huán)境將視為session作用域暖眼。

? 配置方式和基本的作用域相同,只是必須要有web環(huán)境支持纺裁,并配置相應(yīng)的容器監(jiān)聽器或攔截器從而能應(yīng)用這些作用域诫肠,目前先熟悉概念,后續(xù)集成web時(shí)講解具體使用对扶,大家只需要知道有這些作用域就可以了区赵。

Bean的生命周期

? 對(duì)比已經(jīng)學(xué)過的servlet 生命周期(容器啟動(dòng)裝載并實(shí)例化servlet類,初始化servlet浪南,調(diào)用service方法笼才,銷毀servlet)。

? 同樣對(duì)于Spring容器管理的bean也存在生命周期的概念

??在Spring中络凿,Bean的生命周期包括Bean的定義骡送、初始化昂羡、使用和銷毀4個(gè)階段

Bean的定義

? 在Spring中摔踱,通常是通過配置文檔的方式來定義Bean的虐先。

? 在一個(gè)配置文檔中,可以定義多個(gè)Bean派敷。

Bean 的初始化

? 默認(rèn)在IOC容器加載時(shí)蛹批,實(shí)例化對(duì)象。

Spring bean 初始化有兩種方式:

? **方式一:**在配置文檔中通過指定 init-method 屬性來完成篮愉。

publicclassRoleService{// 定義初始化時(shí)需要被調(diào)用的方法publicvoidinit(){System.out.println("RoleService init...");}}

<!-- 通過init-method屬性指定方法 --><beanid="roleService"class="com.xxxx.service.RoleService"init-method="init"></bean>

??方式二:?實(shí)現(xiàn) org.springframework.beans.factory.InitializingBean 接口腐芍。

publicclassRoleServiceimplementsInitializingBean{@OverridepublicvoidafterPropertiesSet()throwsException{System.out.println("RoleService init...");}}

<beanid="roleService"class="com.xxxx.service.RoleService"></bean>

? Bean對(duì)象實(shí)例化過程是在Spring容器初始化時(shí)被實(shí)例化的,但也不是不可改變的试躏,可以通過 lazy-init=“true” 屬性延遲bean對(duì)象的初始化操作猪勇,此時(shí)再調(diào)用getBean 方法時(shí)才會(huì)進(jìn)行bean的初始化操作

Bean 的使用

**方式一:**使用 BeanFactory

// 得到Spring的上下文環(huán)境BeanFactory factory=newClassPathXmlApplicationContext("spring.xml");RoleService roleService=(RoleService)factory.getBean("roleService");

**方式二:**使用 ApplicationContext

// 得到Spring的上下文環(huán)境ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml");RoleService roleService=(RoleService)ac.getBean("roleService");

Bean的銷毀

? 實(shí)現(xiàn)銷毀方式(Spring容器會(huì)維護(hù)bean對(duì)象的管理,可以指定bean對(duì)象的銷毀所要執(zhí)行的方法)颠蕴。

? **步驟一:**實(shí)現(xiàn)銷毀方式(Spring容器會(huì)維護(hù)bean對(duì)象的管理泣刹,可以指定bean對(duì)象的銷毀所要執(zhí)行的方法)

<beanid="roleService"class="com.xxxx.service.RoleService"destroy-method="destroy"></bean>

**步驟二:**通過 AbstractApplicationContext 對(duì)象,調(diào)用其close方法實(shí)現(xiàn)bean的銷毀過程

AbstractApplicationContext ctx=newClassPathXmlApplicationContext("spring.xml");ctx.close();

IOC/DI-控制反轉(zhuǎn)和依賴注入

? ? ? 將對(duì)象實(shí)例化的創(chuàng)建過程轉(zhuǎn)交給外部容器(IOC容器 充當(dāng)工廠角色)去負(fù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末犀被,一起剝皮案震驚了整個(gè)濱河市椅您,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌寡键,老刑警劉巖襟沮,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昌腰,居然都是意外死亡开伏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門遭商,熙熙樓的掌柜王于貴愁眉苦臉地迎上來固灵,“玉大人,你說我怎么就攤上這事劫流∥撞#” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵祠汇,是天一觀的道長仍秤。 經(jīng)常有香客問我,道長可很,這世上最難降的妖魔是什么诗力? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮我抠,結(jié)果婚禮上苇本,老公的妹妹穿的比我還像新娘袜茧。我一直安慰自己,他們只是感情好瓣窄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布笛厦。 她就那樣靜靜地躺著,像睡著了一般俺夕。 火紅的嫁衣襯著肌膚如雪裳凸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天劝贸,我揣著相機(jī)與錄音登舞,去河邊找鬼。 笑死悬荣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疙剑。 我是一名探鬼主播氯迂,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼言缤!你這毒婦竟也來了嚼蚀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤管挟,失蹤者是張志新(化名)和其女友劉穎轿曙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體僻孝,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡导帝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了穿铆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您单。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖荞雏,靈堂內(nèi)的尸體忽然破棺而出虐秦,到底是詐尸還是另有隱情,我是刑警寧澤凤优,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布悦陋,位于F島的核電站,受9級(jí)特大地震影響筑辨,放射性物質(zhì)發(fā)生泄漏俺驶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一棍辕、第九天 我趴在偏房一處隱蔽的房頂上張望痒钝。 院中可真熱鬧秉颗,春花似錦、人聲如沸送矩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栋荸。三九已至菇怀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晌块,已是汗流浹背爱沟。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匆背,地道東北人呼伸。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像钝尸,于是被迫代替她去往敵國和親括享。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容