Spring 5.0.0框架介紹_中英文對(duì)照_第二章

文章作者:Tyan
博客:noahsnail.com

2.Introduction to the Spring Framework

The Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application.

Spring框架是一個(gè)為支持開(kāi)發(fā)Java應(yīng)用提供全面基礎(chǔ)架構(gòu)的Java平臺(tái)。Spring處理基礎(chǔ)架構(gòu),因此你可以集中精力在你有應(yīng)用上。

Spring enables you to build applications from "plain old Java objects" (POJOs) and to apply enterprise services non-invasively to POJOs. This capability applies to the Java SE programming model and to full and partial Java EE.

Spring使你能創(chuàng)建普通Java對(duì)象(POJO)并能非侵入式的將企業(yè)服務(wù)應(yīng)用到普通Java對(duì)象(POJO)上。

Examples of how you, as an application developer, can benefit from the Spring platform:

  • Make a Java method execute in a database transaction without having to deal with transaction APIs.
  • Make a local Java method a remote procedure without having to deal with remote APIs.
  • Make a local Java method a management operation without having to deal with JMX APIs.
  • Make a local Java method a message handler without having to deal with JMS APIs.

作為一個(gè)應(yīng)用開(kāi)發(fā)者,下面是一些你能從Spring平臺(tái)受益的例子:

  • 在一個(gè)數(shù)據(jù)庫(kù)業(yè)務(wù)中執(zhí)行一個(gè)Java方法而不必處理業(yè)務(wù)APIs
  • 使一個(gè)本地的Java方法可以遠(yuǎn)程調(diào)用而不必處理遠(yuǎn)程APIs
  • 使一個(gè)本地Java方法變?yōu)楣芾聿僮鞫槐靥幚鞪MX APIs
  • 使一個(gè)本地Java方法變?yōu)橄⑻幚砥鞫槐靥幚鞪MS APIs

2.1 Dependency Injection and Inversion of Control

A Java application?—?a loose term that runs the gamut from constrained, embedded applications to n-tier, server-side enterprise applications?—?typically consists of objects that collaborate to form the application proper. Thus the objects in an application have dependencies on each other.

Java應(yīng)用——一個(gè)不精確的術(shù)語(yǔ),既可以表示受限制的嵌入式應(yīng)用又可以表示N層服務(wù)端的企業(yè)級(jí)應(yīng)用——通常由許多對(duì)象構(gòu)成,這些對(duì)象協(xié)作形成完整的應(yīng)用程序。因此一個(gè)應(yīng)用程序中的對(duì)象是相互依賴的。

Although the Java platform provides a wealth of application development functionality, it lacks the means to organize the basic building blocks into a coherent whole, leaving that task to architects and developers. Although you can use design patterns such as Factory, Abstract Factory, Builder, Decorator, and Service Locator to compose the various classes and object instances that make up an application, these patterns are simply that: best practices given a name, with a description of what the pattern does, where to apply it, the problems it addresses, and so forth. Patterns are formalized best practices that you must implement yourself in your application.

盡管Java平臺(tái)提供了大量的應(yīng)用開(kāi)發(fā)功能,但是它缺少把這些基本構(gòu)建模塊組織成一個(gè)連貫整體的方法,并把組織基本構(gòu)建模塊的任務(wù)留給了架構(gòu)師和開(kāi)發(fā)者。雖然你可以使用設(shè)計(jì)模式例如工廠模式、抽象工廠模式、生成器模式、裝飾模式、服務(wù)定位模式來(lái)創(chuàng)建構(gòu)成應(yīng)用的各種類和對(duì)象實(shí)例,但這些設(shè)計(jì)模式很簡(jiǎn)單:命名的最佳方法、模式的作用描述、應(yīng)用模式的位置、模式解決的問(wèn)題等等。模式使最佳實(shí)踐形式化了,這意味著你必須在你的應(yīng)用中自己實(shí)現(xiàn)它

The Spring Framework Inversion of Control (IoC) component addresses this concern by providing a formalized means of composing disparate components into a fully working application ready for use. The Spring Framework codifies formalized design patterns as first-class objects that you can integrate into your own application(s). Numerous organizations and institutions use the Spring Framework in this manner to engineer robust, maintainable applications.

Spring框架中的控制反轉(zhuǎn)(IoC)組件通過(guò)提供一種形式化方法解決了這個(gè)問(wèn)題,這個(gè)形式化方法將不同的組件創(chuàng)建到一個(gè)隨時(shí)可用的完整的工作應(yīng)用中。Spring框架將形式化的設(shè)計(jì)模式編碼成了你可以集成到你自己的應(yīng)用中的最好對(duì)象。許多組織和機(jī)構(gòu)用這種方式應(yīng)用Spring框架來(lái)構(gòu)建魯棒的、可維護(hù)的應(yīng)用。

Background
"The question is, what aspect of control are [they] inverting?" Martin Fowler posed this question about Inversion of Control (IoC) on his site in 2004. Fowler suggested renaming the principle to make it more self-explanatory and came up with Dependency Injection.

?

背景
"問(wèn)題是什么是控制反轉(zhuǎn)?" 2004年Martin Fowler在他的網(wǎng)站上提出了這個(gè)關(guān)于控制反轉(zhuǎn)(IoC)問(wèn)題。Fowler建議重新命名這個(gè)原理使它更一目了然并且提出了依賴注入

2.2 Modules

The Spring Framework consists of features organized into about 20 modules. These modules are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented Programming), Instrumentation, Messaging, and Test, as shown in the following diagram.

Spring框架包含的功能大約由20個(gè)模塊組成。這些模塊按組可分為核心容器、數(shù)據(jù)訪問(wèn)/集成,Web,AOP(面向切面編程)、設(shè)備、消息和測(cè)試,如下圖所示。

Figure 2.1. Overview of the Spring Framework

image

The following sections list the available modules for each feature along with their artifact names and the topics they cover. Artifact names correlate to artifact IDs used in Dependency Management tools.

接下來(lái)的章節(jié)列出了每個(gè)功能可用的模塊、它們的工件名字以及它們包含的主題。工件名字與依賴管理工具中使用的artifact IDs有關(guān)。

2.2.1 Core Container

The Core Container consists of the spring-core, spring-beans, spring-context, spring-context-support, and spring-expression (Spring Expression Language) modules.

核心容器功能包括spring-core, spring-beans, spring-context, spring-context-support, and spring-expression(Spring表現(xiàn)語(yǔ)言)模塊。

The spring-core and spring-beans modules provide the fundamental parts of the framework, including the IoC and Dependency Injection features. The BeanFactory is a sophisticated implementation of the factory pattern. It removes the need for programmatic singletons and allows you to decouple the configuration and specification of dependencies from your actual program logic.

spring-corespring-beans模塊提供了框架的基礎(chǔ)結(jié)構(gòu)部分,包含控制反轉(zhuǎn)(IoC)和依賴注入(DI)功能。BeanFactory是工廠模式的高級(jí)實(shí)現(xiàn)。它去掉了程序單例模式的需求并且允許你從實(shí)際的程序邏輯中解耦配置和依賴關(guān)系。

The Context (spring-context) module builds on the solid base provided by the Core and Beans modules: it is a means to access objects in a framework-style manner that is similar to a JNDI registry. The Context module inherits its features from the Beans module and adds support for internationalization (using, for example, resource bundles), event propagation, resource loading, and the transparent creation of contexts by, for example, a Servlet container. The Context module also supports Java EE features such as EJB, JMX, and basic remoting. The ApplicationContext interface is the focal point of the Context module.spring-context-support provides support for integrating common third-party libraries into a Spring application context, in particular for caching (EhCache, JCache) and scheduling (CommonJ, Quartz).

上下文(spring-context)模塊建立在由Core模塊和Beans模塊提供的堅(jiān)實(shí)基礎(chǔ)上:它是在類似于JNDI注冊(cè)表式的框架風(fēng)格模式中訪問(wèn)對(duì)象的一種方法。上下文模塊繼承了Beans模塊的功能,并添加了對(duì)國(guó)際化(例如使用資源捆綁)、事件傳播、資源加載和上下文透明創(chuàng)建(例如通過(guò)Servlet容器)的支持。上下文模塊也支持Java EE功能例如EJB,JMX和基本的遠(yuǎn)程。ApplicationContext接口是上下文模塊的焦點(diǎn)。spring-context-support支持將第三方庫(kù)集成進(jìn)Spring應(yīng)用程序上下文中,特別是緩存(EhCache, JCache)和定時(shí)執(zhí)行(CommonJ, Quartz)。

The spring-expression module provides a powerful Expression Language for querying and manipulating an object graph at runtime. It is an extension of the unified expression language (unified EL) as specified in the JSP 2.1 specification. The language supports setting and getting property values, property assignment, method invocation, accessing the content of arrays, collections and indexers, logical and arithmetic operators, named variables, and retrieval of objects by name from Spring’s IoC container. It also supports list projection and selection as well as common list aggregations.

spring-expression模塊提供了強(qiáng)大的表達(dá)式語(yǔ)言用來(lái)在運(yùn)行時(shí)查詢和操作對(duì)象圖。它是JSP 2.1規(guī)范中統(tǒng)一表達(dá)式語(yǔ)言(unified EL)的擴(kuò)展。這個(gè)語(yǔ)言支持setting和getting屬性值,屬性分配,方法調(diào)用,訪問(wèn)數(shù)組、集合和索引器的內(nèi)容,邏輯和算術(shù)操作,變量命名,從Spring Ioc容器中通過(guò)名字檢索對(duì)象。它也支持它還支持列表投影、選擇以及常見(jiàn)的列表聚合。

2.2.2 AOP and Instrumentation

The spring-aop module provides an AOP Alliance-compliant aspect-oriented programming implementation allowing you to define, for example, method interceptors and pointcuts to cleanly decouple code that implements functionality that should be separated. Using source-level metadata functionality, you can also incorporate behavioral information into your code, in a manner similar to that of .NET attributes.

spring-aop模塊提供了AOP Alliance-compliant(AOP聯(lián)盟)面向切面編程的實(shí)現(xiàn),例如允許你自定義方法攔截器和切入點(diǎn)來(lái)清晰的解耦功能實(shí)現(xiàn)上應(yīng)該分開(kāi)的代碼。使用源碼級(jí)的元數(shù)據(jù)功能,你也可以將行為信息合并到你的代碼中,在某種程度上這類似于.NET的屬性值。

The separate spring-aspects module provides integration with AspectJ.

獨(dú)立的spring-aspects模塊提供了與AspectJ的集成。

The spring-instrument module provides class instrumentation support and classloader implementations to be used in certain application servers. The spring-instrument-tomcat module contains Spring’s instrumentation agent for Tomcat.

spring-instrument模塊提供了類設(shè)備支持和類加載器的實(shí)現(xiàn),它們可以在某些應(yīng)用服務(wù)器中使用。spring-instrument-tomcat模塊包含了Tomcat的Spring設(shè)備代理。

2.2.3 Messaging

Spring Framework 4 includes a spring-messaging module with key abstractions from the Spring Integration project such as Message, MessageChannel, MessageHandler, and others to serve as a foundation for messaging-based applications. The module also includes a set of annotations for mapping messages to methods, similar to the Spring MVC annotation based programming model.

Spring 4框架中包含了spring-messaging模塊,它對(duì)Spring集成項(xiàng)目例如Message, MessageChannel, MessageHandler和其它作為消息應(yīng)用服務(wù)基礎(chǔ)的項(xiàng)目進(jìn)行了重要的抽象。這個(gè)模塊也包含了一系列將消息映射到方法上的注解,這個(gè)注解與基于編程模型Spring MVC注解類似。

2.2.4 Data Access/Integration

The Data Access/Integration layer consists of the JDBC, ORM, OXM, JMS, and Transaction modules.

數(shù)據(jù)訪問(wèn)/集成層包括JDBC,ORM,OXM,JMS和業(yè)務(wù)模塊。

The spring-jdbc module provides a JDBC-abstraction layer that removes the need to do tedious JDBC coding and parsing of database-vendor specific error codes.

spring-jdbc模塊提供了JDBC抽象層,不需要再編寫(xiě)單調(diào)的JDBC代碼,解析數(shù)據(jù)庫(kù)提供商指定的錯(cuò)誤編碼。

The spring-tx module supports programmatic and declarative transaction management for classes that implement special interfaces and for all your POJOs (Plain Old Java Objects).

spring-tx模塊為實(shí)現(xiàn)指定接口和所有的普通Java對(duì)象(POJOs)的類提供編程式(programmatic)和聲明式(declarative)的業(yè)務(wù)管理。

The spring-orm module provides integration layers for popular object-relational mapping APIs, including JPA and Hibernate. Using the spring-orm module you can use these O/R-mapping frameworks in combination with all of the other features Spring offers, such as the simple declarative transaction management feature mentioned previously.

spring-orm模塊提供流行的對(duì)象關(guān)系映射APIs的集成層,包括JPA和Hibernate。在使用spring-orm模塊時(shí),你可以將Spring的其它功能與這些O/R-mapping框架結(jié)合起來(lái)使用,例如前面提到的簡(jiǎn)單聲明式業(yè)務(wù)管理的功能。

The spring-oxm module provides an abstraction layer that supports Object/XML mapping implementations such as JAXB, Castor, JiBX and XStream.

spring-oxm模塊提供對(duì)Object/XML映射實(shí)現(xiàn)例如JAXB,Castor,JiBx和XStream的抽象層。

The spring-jms module (Java Messaging Service) contains features for producing and consuming messages. Since Spring Framework 4.1, it provides integration with the spring-messaging module.

spring-jms模塊(Java消息服務(wù))包含產(chǎn)生和處理消息的功能。從Spring 4.1框架開(kāi)始它提供了與spring-messaging的集成。

2.2.5 Web

The Web layer consists of the spring-web, spring-webmvc and spring-websocket modules.

網(wǎng)絡(luò)層包含spring-web, spring-webmvcspring-websocket模塊。

The spring-web module provides basic web-oriented integration features such as multipart file upload functionality and the initialization of the IoC container using Servlet listeners and a web-oriented application context. It also contains an HTTP client and the web-related parts of Spring’s remoting support.

spring-web模塊提供基本的面向網(wǎng)絡(luò)集成功能,例如multipart文件上傳功能,使用Servlet監(jiān)聽(tīng)器來(lái)初始化Ioc容器和面向網(wǎng)絡(luò)的應(yīng)用程序上下文。它也包含了HTTP客戶端和Spring遠(yuǎn)程支持中網(wǎng)絡(luò)相關(guān)的部分。

The spring-webmvc module (also known as the Web-Servlet module) contains Spring’s model-view-controller (MVC) and REST Web Services implementation for web applications. Spring’s MVC framework provides a clean separation between domain model code and web forms and integrates with all of the other features of the Spring Framework.

spring-webmvc模塊(也被稱為Web-Servlet模塊)包含了Spring的model-view-controller(MVC)和REST Web Services的網(wǎng)絡(luò)應(yīng)用實(shí)現(xiàn)。Spring的MVC框架提供了對(duì)領(lǐng)域模型代碼,web表單,Spring框架其他功能的完全分離。

2.2.6 Test

The spring-test module supports the unit testing and integration testing of Spring components with JUnit or TestNG. It provides consistent loading of Spring ApplicationContexts and caching of those contexts. It also provides mock objects that you can use to test your code in isolation.

spring-test模塊支持單元測(cè)試,Spring組件和JUnit或TestNG的集成測(cè)試。它提供了Spring的ApplicationContexts加載和這些上下文緩存的一致。它也提供了可以單獨(dú)測(cè)試代碼的模擬對(duì)象。

2.3 Usage scenarios

The building blocks described previously make Spring a logical choice in many scenarios, from embedded applications that run on resource-constrained devices to full-fledged enterprise applications that use Spring’s transaction management functionality and web framework integration.

前面描述的搭積木方式使Spring在許多場(chǎng)景中都有一個(gè)合理選擇,從運(yùn)行在資源受限的嵌入式應(yīng)用到全面成熟的企業(yè)級(jí)應(yīng)用都在使用Spring的業(yè)務(wù)管理功能和網(wǎng)絡(luò)框架集成。

Figure 2.2. Typical full-fledged Spring web application

image

Spring’s declarative transaction management features make the web application fully transactional, just as it would be if you used EJB container-managed transactions. All your custom business logic can be implemented with simple POJOs and managed by Spring’s IoC container. Additional services include support for sending email and validation that is independent of the web layer, which lets you choose where to execute validation rules. Spring’s ORM support is integrated with JPA and Hibernate; for example, when using Hibernate, you can continue to use your existing mapping files and standard Hibernate SessionFactory configuration. Form controllers seamlessly integrate the web-layer with the domain model, removing the need for ActionForms or other classes that transform HTTP parameters to values for your domain model.

Spring的聲明式業(yè)務(wù)管理功能使web應(yīng)用全面的業(yè)務(wù)化,如果你用過(guò)EJB容器管理業(yè)務(wù)的話你會(huì)發(fā)現(xiàn)它們基本一樣。你所有自定義的業(yè)務(wù)邏輯都可以用POJOs實(shí)現(xiàn)并通過(guò)Spring的IoC容器管理。附加業(yè)務(wù)包括支持郵件發(fā)送和驗(yàn)證,這個(gè)是獨(dú)立于web層之外的,你可以自由選擇驗(yàn)證規(guī)則執(zhí)行的位置。Spring對(duì)ORM的支持與JPA和Hibernate進(jìn)行了集成;例如,當(dāng)你使用Hibernate時(shí),你可以繼續(xù)使用你現(xiàn)有的映射文件和標(biāo)準(zhǔn)的Hibernate SessionFactory配置。表單控制器被無(wú)縫的將web層和領(lǐng)域模型進(jìn)行了集成,對(duì)于你的領(lǐng)域模型來(lái)講不再需要ActionForms或其它的將HTTP參數(shù)轉(zhuǎn)換成值的

Figure 2.3. Spring middle-tier using a third-party web framework

image

Sometimes circumstances do not allow you to completely switch to a different framework. The Spring Framework does not force you to use everything within it; it is not an all-or-nothing solution. Existing front-ends built with Struts, Tapestry, JSF or other UI frameworks can be integrated with a Spring-based middle-tier, which allows you to use Spring transaction features. You simply need to wire up your business logic using an ApplicationContext and use a WebApplicationContext to integrate your web layer.

有時(shí)候環(huán)境不允許你完全轉(zhuǎn)成一個(gè)不同的框架。Spring框架強(qiáng)迫你都采用它內(nèi)部的東西;它不是一個(gè)要么全有要么全無(wú)的解決方案。現(xiàn)有的采用Struts,Tapestry,JSF或其它UI框架構(gòu)建的前端可以與基于Spring的中間層進(jìn)行集成,這可以讓你使用Spring的業(yè)務(wù)功能。你只需要簡(jiǎn)單的用ApplicationContextWebApplicationContext綁定你的業(yè)務(wù)邏輯然后集成到web層即可。

Figure 2.4. Remoting usage scenario

image

When you need to access existing code through web services, you can use Spring’s Hessian-, Rmi- or HttpInvokerProxyFactoryBean classes. Enabling remote access to existing applications is not difficult.

當(dāng)你需要通過(guò)web服務(wù)訪問(wèn)現(xiàn)有代碼時(shí),你可以使用Spring的Hessian-, Rmi-HttpInvokerProxyFactoryBean類。這能讓遠(yuǎn)程訪問(wèn)現(xiàn)有應(yīng)用變得很容易。

Figure 2.5. EJBs - Wrapping existing POJOs

image

The Spring Framework also provides an access and abstraction layer for Enterprise JavaBeans, enabling you to reuse your existing POJOs and wrap them in stateless session beans for use in scalable, fail-safe web applications that might need declarative security.

Spring框架也為企業(yè)JavaBeans提供了訪問(wèn)和抽象層,使你能重用你現(xiàn)有的POJOs,為了可擴(kuò)展使用可以將它們包裝成無(wú)狀態(tài)的session beans,自動(dòng)防故障的web應(yīng)用可能需要聲明安全。

2.3.1 Dependency Management and Naming Conventions

Dependency management and dependency injection are different things. To get those nice features of Spring into your application (like dependency injection) you need to assemble all the libraries needed (jar files) and get them onto your classpath at runtime, and possibly at compile time. These dependencies are not virtual components that are injected, but physical resources in a file system (typically). The process of dependency management involves locating those resources, storing them and adding them to classpaths. Dependencies can be direct (e.g. my application depends on Spring at runtime), or indirect (e.g. my application depends on commons-dbcp which depends on commons-pool). The indirect dependencies are also known as "transitive" and it is those dependencies that are hardest to identify and manage.

依賴管理和依賴注入是完全不同的兩件事。為了能你的應(yīng)用中使用Spring的優(yōu)秀特性(像依賴注入),你需要收集所有必要的庫(kù)(jar文件)并在運(yùn)行時(shí)將它們添加到classpath中,有可能在編譯時(shí)就需要添加。這些依賴不是要被注入的虛擬組建,而是文件系統(tǒng)中的物理資源(通常情況下)。這些依賴管理的過(guò)程包括資源的定位、存儲(chǔ)和添加到classpath中。依賴可以是直接的(例如:我的應(yīng)用在運(yùn)行時(shí)依賴Spring),或間接的(例如:我的應(yīng)用依賴commons-dbcp,而它依賴commons-pool)。間接依賴也被稱為"傳遞式"的,這些依賴也是最難識(shí)別和管理的。

If you are going to use Spring you need to get a copy of the jar libraries that comprise the pieces of Spring that you need. To make this easier Spring is packaged as a set of modules that separate the dependencies as much as possible, so for example if you don’t want to write a web application you don’t need the spring-web modules. To refer to Spring library modules in this guide we use a shorthand naming convention spring-* or spring-*.jar, where * represents the short name for the module (e.g. spring-core, spring-webmvc, spring-jms, etc.). The actual jar file name that you use is normally the module name concatenated with the version number (e.g. spring-core-5.0.0.BUILD-SNAPSHOT.jar).

如果你想使用Spring,你需要有包含你需要的Spirng功能的jar庫(kù)副本。為了使這個(gè)更容易,Spring被打包成了一系列盡可能將依賴分離開(kāi)的模塊,例如你不想寫(xiě)web應(yīng)用那你就不需要spring-web模塊。為了在本指南中談及Spring的庫(kù)模塊,我們使用了一個(gè)簡(jiǎn)寫(xiě)命名約定spring-*spring-*.jar*表示模塊的簡(jiǎn)寫(xiě)名字(例如spring-core, spring-webmvc, spring-jms等等)。實(shí)際中你使用的jar文件名字通常是模塊名加上版本號(hào)(例如spring-core-5.0.0.BUILD-SNAPSHOT.jar)。

Each release of the Spring Framework will publish artifacts to the following places:

  • Maven Central, which is the default repository that Maven queries, and does not require any special configuration to use. Many of the common libraries that Spring depends on also are available from Maven Central and a large section of the Spring community uses Maven for dependency management, so this is convenient for them. The names of the jars here are in the form spring-*-<version>.jar and the Maven groupId is org.springframework.
  • In a public Maven repository hosted specifically for Spring. In addition to the final GA releases, this repository also hosts development snapshots and milestones. The jar file names are in the same form as Maven Central, so this is a useful place to get development versions of Spring to use with other libraries deployed in Maven Central. This repository also contains a bundle distribution zip file that contains all Spring jars bundled together for easy download.
    So the first thing you need to decide is how to manage your dependencies: we generally recommend the use of an automated system like Maven, Gradle or Ivy, but you can also do it manually by downloading all the jars yourself.

Spring框架的每次發(fā)布都會(huì)下面的地方公布artifacts:

  • Maven Central,Maven查詢的默認(rèn)倉(cāng)庫(kù),使用時(shí)不需要任何特定的配置。Spring依賴的許多共通庫(kù)也可以從Maven Central獲得,Spring社區(qū)的很大一部分都在使用Maven進(jìn)行依賴管理,因此這對(duì)他們來(lái)說(shuō)是很方便的。jar包的命名形式是spring-*-<version>.jar,Maven GroupId是org.springframework
  • 由Spring掌管的公開(kāi)Maven庫(kù)。除了最終的GA release(公開(kāi)可獲得的版本)之外,這個(gè)倉(cāng)庫(kù)也有開(kāi)發(fā)版本的快照和milestone版本。jar包的命名形式和Maven Central一樣,這是一個(gè)可以使用Spring開(kāi)發(fā)版本有用地方,而其它的庫(kù)部署在Maven Central。這個(gè)庫(kù)也包含的捆綁分布的zip文件,這個(gè)zip文件中所有的Spring jar包被捆綁到一起很容易下載。

You will find bellow the list of Spring artifacts. For a more complete description of each modules, see Section 2.2, “Modules”.

你將在下面找到Spring artifacts列表。想要每個(gè)模塊更全面的描述,請(qǐng)看2.2小節(jié)。

Table 2.1. Spring Framework Artifacts

image

Spring Dependencies and Depending on Spring

Although Spring provides integration and support for a huge range of enterprise and other external tools, it intentionally keeps its mandatory dependencies to an absolute minimum: you shouldn’t have to locate and download (even automatically) a large number of jar libraries in order to use Spring for simple use cases. For basic dependency injection there is only one mandatory external dependency, and that is for logging (see below for a more detailed description of logging options).

雖然Spring提供集成并支持大范圍內(nèi)的企業(yè)和其它外部工具,但它有意使它的強(qiáng)制性依賴到一個(gè)絕對(duì)最小化的程度:對(duì)于簡(jiǎn)單的用例你不應(yīng)該為了使用Spring而定位和下載(即使是自動(dòng)的)許多jar庫(kù)。對(duì)于基本的依賴注入僅有一個(gè)強(qiáng)制性的外部依賴,那個(gè)依賴是關(guān)于日志的(在下面可以看到日志選擇更詳細(xì)的描述)。

Next we outline the basic steps needed to configure an application that depends on Spring, first with Maven and then with Gradle and finally using Ivy. In all cases, if anything is unclear, refer to the documentation of your dependency management system, or look at some sample code - Spring itself uses Gradle to manage dependencies when it is building, and our samples mostly use Gradle or Maven.

接下來(lái)我們概述配置一個(gè)依賴于Spring的應(yīng)用需要的基本步驟,首先Maven的,其次是Gradle的,最后是Ivy的。在所有的案例中,如果有任何不清楚的地方,請(qǐng)參考你的依賴管理系統(tǒng)的文檔,或者看一些示例代碼——Spring本身構(gòu)建時(shí)使用Gradle來(lái)管理依賴,我們例子中大多數(shù)是使用Gradle和Maven的。

Maven Dependency Management

If you are using Maven for dependency management you don’t even need to supply the logging dependency explicitly. For example, to create an application context and use dependency injection to configure an application, your Maven dependencies will look like this:

如果你正在使用Maven來(lái)進(jìn)行依賴管理,那你不必顯式的提供日志依賴。例如,為了創(chuàng)建一個(gè)應(yīng)用上下文,使用依賴注入來(lái)配置一個(gè)應(yīng)用,你的Maven依賴看上去是這樣的:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.0.BUILD-SNAPSHOT</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

That’s it. Note the scope can be declared as runtime if you don’t need to compile against Spring APIs, which is typically the case for basic dependency injection use cases.

就是它。注意如果你不需要編譯Spring APIs,scope可以被聲明成rumtime,這是典型的基本依賴注入的情況。

The example above works with the Maven Central repository. To use the Spring Maven repository (e.g. for milestones or developer snapshots), you need to specify the repository location in your Maven configuration. For full releases:

上面的例子是采用Maven中心倉(cāng)庫(kù)的。為了使用Spring Maven倉(cāng)庫(kù)(例如:使用milestone版本或snapshot版本),你需要在Maven配置中指定倉(cāng)庫(kù)的位置,完整的版本:

<repositories>
    <repository>
        <id>io.spring.repo.maven.release</id>
        <url>http://repo.spring.io/release/</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
</repositories>

For milestones:
對(duì)于milestone版本:

<repositories>
    <repository>
        <id>io.spring.repo.maven.milestone</id>
        <url>http://repo.spring.io/milestone/</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
</repositories>

And for snapshots:
對(duì)于snapshot版本:

<repositories>   
    <repository>
        <id>io.spring.repo.maven.snapshot</id>
        <url>http://repo.spring.io/snapshot/</url>
        <snapshots><enabled>true</enabled></snapshots>
    </repository>
</repositories>

Maven "Bill Of Materials" Dependency

It is possible to accidentally mix different versions of Spring JARs when using Maven. For example, you may find that a third-party library, or another Spring project, pulls in a transitive dependency to an older release. If you forget to explicitly declare a direct dependency yourself, all sorts of unexpected issues can arise.

在使用Maven時(shí),有可能會(huì)偶然的將不同版本的Spring JARs混合起來(lái)。例如,你可能找到一個(gè)第三方庫(kù),或另一個(gè)Spring項(xiàng)目,通過(guò)傳遞依賴進(jìn)入了一個(gè)更舊的版本。如果你忘了自己顯式的聲明一個(gè)直接依賴,會(huì)產(chǎn)生各種意想不到的問(wèn)題。

To overcome such problems Maven supports the concept of a "bill of materials" (BOM) dependency. You can import the spring-framework-bom in your dependencyManagement section to ensure that all spring dependencies (both direct and transitive) are at the same version.

為了解決這種問(wèn)題,Maven支持"材料清單"(BOM)依賴的概念。你可以在你的dependencyManagement部分導(dǎo)入spring-framework-bom來(lái)確保所有的Spring依賴(直接和傳遞的)都是同一個(gè)版本。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>5.0.0.BUILD-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

An added benefit of using the BOM is that you no longer need to specify the <version> attribute when depending on Spring Framework artifacts:

使用BOM的額外好處是當(dāng)依賴Spring框架的artifacts時(shí)你不再需要指定<version>屬性:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
<dependencies>

Gradle Dependency Management

To use the Spring repository with the Gradle build system, include the appropriate URL in the repositories section:

為了在Gradle構(gòu)建系統(tǒng)中使用Spring倉(cāng)庫(kù),在repositories部分需要包含合適的URL:

repositories {
    mavenCentral()
    // and optionally...
    maven { url "http://repo.spring.io/release" }
}

You can change the repositories URL from /release to /milestone or /snapshot as appropriate. Once a repository has been configured, you can declare dependencies in the usual Gradle way:

當(dāng)合適的時(shí)候你可以修改repositories的URL從/release/milestone/snapshot。一旦一個(gè)倉(cāng)庫(kù)被配置了,你可以用通常的Gradle方式聲明依賴:

dependencies {
    compile("org.springframework:spring-context:5.0.0.BUILD-SNAPSHOT")
    testCompile("org.springframework:spring-test:5.0.0.BUILD-SNAPSHOT")
}

Ivy Dependency Management

If you prefer to use Ivy to manage dependencies then there are similar configuration options.

如果你更喜歡使用Ivy來(lái)管理依賴,這有類似的配置選擇。

To configure Ivy to point to the Spring repository add the following resolver to your ivysettings.xml:

為了配置Ivy指定Spring倉(cāng)庫(kù),添加下面的解析器到你的ivysettings.xml:

<resolvers>
    <ibiblio name="io.spring.repo.maven.release"
            m2compatible="true"
            root="http://repo.spring.io/release/"/>
</resolvers>

You can change the root URL from /release/ to /milestone/ or /snapshot/ as appropriate.

當(dāng)合適的時(shí)候你可以更改根URL從repositories的URL從/release/milestone/snapshot

Once configured, you can add dependencies in the usual way. For example (in ivy.xml):

一旦配置了,你可以通過(guò)一般的方式添加依賴。例如(在ivy.xml):

<dependency org="org.springframework"
    name="spring-core" rev="5.0.0.BUILD-SNAPSHOT" conf="compile->runtime"/>

Distribution Zip Files

Although using a build system that supports dependency management is the recommended way to obtain the Spring Framework, it is still possible to download a distribution zip file.

盡管使用一個(gè)支持依賴管理的構(gòu)建系統(tǒng)是獲得Spring框架的推薦方式,但仍然可以下載發(fā)行版的Zip文件。

Distribution zips are published to the Spring Maven Repository (this is just for our convenience, you don’t need Maven or any other build system in order to download them).

發(fā)行版的zips是被發(fā)布到Spring Maven倉(cāng)庫(kù)(這只是為了我們的方便,為了下載它們你不需要Maven或任何其它的構(gòu)建系統(tǒng))。

To download a distribution zip open a web browser to http://repo.spring.io/release/org/springframework/spring and select the appropriate subfolder for the version that you want. Distribution files end -dist.zip, for example spring-framework-{spring-version}-RELEASE-dist.zip. Distributions are also published for milestones and snapshots.

為了下載發(fā)行版zip,打開(kāi)瀏覽器輸入http://repo.spring.io/release/org/springframework/spring,然后選擇你想要的版本的合適子文件夾。發(fā)行版文件以-dist.zip結(jié)尾,例如spring-framework-{spring-version}-RELEASE-dist.zip。發(fā)行版也可以公布milestone版本或snapshots版本。

2.3.2 Logging

Logging is a very important dependency for Spring because a) it is the only mandatory external dependency, b) everyone likes to see some output from the tools they are using, and c) Spring integrates with lots of other tools all of which have also made a choice of logging dependency. One of the goals of an application developer is often to have unified logging configured in a central place for the whole application, including all external components. This is more difficult than it might have been since there are so many choices of logging framework.

日志對(duì)于Spring來(lái)說(shuō)是一個(gè)非常重要的依賴,因?yàn)椋?em>a)它是唯一的強(qiáng)制性外部依賴,b)每個(gè)人都喜歡從他們使用的工具中看到一些輸出,c)Spring集成了許多其它的工具,這些工具也選擇了日志依賴。應(yīng)用開(kāi)發(fā)者的一個(gè)目標(biāo)就是對(duì)于整個(gè)應(yīng)用來(lái)講,經(jīng)常要有一個(gè)中心地方來(lái)進(jìn)行日志的統(tǒng)一配置,包括所有的外部組件。比它更困難的可能是有太多的日志框架去選擇。

The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We compile against JCL and we also make JCL Log objects visible for classes that extend the Spring Framework. It’s important to users that all versions of Spring use the same logging library: migration is easy because backwards compatibility is preserved even with applications that extend Spring. The way we do this is to make one of the modules in Spring depend explicitly on commons-logging (the canonical implementation of JCL), and then make all the other modules depend on that at compile time. If you are using Maven for example, and wondering where you picked up the dependency on commons-logging, then it is from Spring and specifically from the central module called spring-core.

Spring中的強(qiáng)制日志依賴是Jakarta Commons Logging API (JCL)。我們編譯JCL并使JCLlog對(duì)象對(duì)類是可見(jiàn)的,這擴(kuò)展了Spring框架。所有版本的Spring采用同一個(gè)日志庫(kù):移植是容易的,因?yàn)榧词箲?yīng)用擴(kuò)展了Spring但保留了向后兼容性,這一點(diǎn)對(duì)用戶來(lái)說(shuō)很重要。我們實(shí)現(xiàn)這個(gè)的方式是讓Spring的模塊之一顯式的依賴commons-logging(JCL的標(biāo)準(zhǔn)實(shí)現(xiàn)),然后使其它模塊在編譯時(shí)依賴這個(gè)模塊。例如如果你在使用Maven,想找出依賴于commons-logging的依賴在哪,它在Spring中,更確切的說(shuō)它是在Spring的中心模塊spring-core中。

The nice thing about commons-logging is that you don’t need anything else to make your application work. It has a runtime discovery algorithm that looks for other logging frameworks in well known places on the classpath and uses one that it thinks is appropriate (or you can tell it which one if you need to). If nothing else is available you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short). You should find that your Spring application works and logs happily to the console out of the box in most situations, and that’s important.

關(guān)于commons-logging的一件好事是要使你的應(yīng)用工作你不需要任何其它的東西。它有一個(gè)運(yùn)行時(shí)發(fā)現(xiàn)算法,這個(gè)算法能尋找其它的日志框架在知名的classpath中,并使用一個(gè)它認(rèn)為是合適的(或者你告訴它你想用哪個(gè)如果你需要的話)。如果找不到任何別的你可以從JDK中找到一個(gè)非常美好漂亮的日志(java.util.logging或縮寫(xiě)為JUL)。在大多數(shù)環(huán)境中你可以發(fā)現(xiàn)你的Spring應(yīng)用恰當(dāng)?shù)剡\(yùn)行并輸出日志到控制臺(tái)輸出框中,那是很重要的。

Not Using Commons Logging

Unfortunately, the runtime discovery algorithm in commons-logging, while convenient for the end-user, is problematic. If we could turn back the clock and start Spring now as a new project it would use a different logging dependency. The first choice would probably be the Simple Logging Facade for Java ( SLF4J), which is also used by a lot of other tools that people use with Spring inside their applications.

不幸的是, 雖然commons-logging的運(yùn)行時(shí)發(fā)現(xiàn)算法對(duì)于終端用戶是方便的,但它是有問(wèn)題的。如果我們將時(shí)鐘回?fù)埽裇pring作為一個(gè)新項(xiàng)目重新開(kāi)始,將會(huì)選擇一個(gè)不同的日志依賴。第一個(gè)選擇可能是Simple Logging Facade for Java(SLF4J),應(yīng)用內(nèi)部使用Spring的人使用的許多其它工具也用了SLF4J。

There are basically two ways to switch off commons-logging:

  1. Exclude the dependency from the spring-core module (as it is the only module that explicitly depends on commons-logging)
  2. Depend on a special commons-logging dependency that replaces the library with an empty jar (more details can be found in the SLF4J FAQ)

這兒有兩種方式關(guān)掉commons-logging:

  1. spring-core模塊排除依賴(因?yàn)樗俏ㄒ坏娘@式依賴)commons-logging的模塊
  2. 依賴于一個(gè)特定的commons-logging依賴,用一個(gè)空jar替換這個(gè)依賴(更多細(xì)節(jié)可以在SLF4J FAQ中找到)。

To exclude commons-logging, add the following to your dependencyManagement section:

為了排除commons-logging,把下面的內(nèi)容加入到你的dependencyManagement部分:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.0.0.BUILD-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

Now this application is probably broken because there is no implementation of the JCL API on the classpath, so to fix it a new one has to be provided. In the next section we show you how to provide an alternative implementation of JCL using SLF4J as an example.

現(xiàn)在這個(gè)應(yīng)用可能是壞了的,因?yàn)樵赾lasspath中沒(méi)有JCL API的實(shí)現(xiàn),為了解決這個(gè)問(wèn)題必須提供一個(gè)新的實(shí)現(xiàn)。在接下來(lái)的部分我們將向你展示怎樣提供一個(gè)JCL替代實(shí)現(xiàn),使用SLF4J就是一個(gè)例子。

Using SLF4J

SLF4J is a cleaner dependency and more efficient at runtime than commons-logging because it uses compile-time bindings instead of runtime discovery of the other logging frameworks it integrates. This also means that you have to be more explicit about what you want to happen at runtime, and declare it or configure it accordingly. SLF4J provides bindings to many common logging frameworks, so you can usually choose one that you already use, and bind to that for configuration and management.

SLF4J是一個(gè)更純凈的依賴并且在運(yùn)行時(shí)比commons-logging更有效,因?yàn)樗褂镁幾g時(shí)綁定來(lái)代替運(yùn)行時(shí)查找集成的其它日志框架。這也意味著你必須更清楚你想要運(yùn)行時(shí)發(fā)生什么,然后相應(yīng)的聲明它或配置它。SLF4J提供跟許多常用日志框架的綁定,因此你通常可以選擇一個(gè)你正在使用的日志框架,然后綁定到配置和管理上。

SLF4J provides bindings to many common logging frameworks, including JCL, and it also does the reverse: bridges between other logging frameworks and itself. So to use SLF4J with Spring you need to replace the commons-logging dependency with the SLF4J-JCL bridge. Once you have done that then logging calls from within Spring will be translated into logging calls to the SLF4J API, so if other libraries in your application use that API, then you have a single place to configure and manage logging.

SLF4J提供跟許多常用日志框架的綁定,包括JCL,它做的恰恰相反,建立其它日志框架和它自己的紐帶。因此為了在Spring中使用SLF4J,你需要用SLF4J-JCL連接器取替換commons-logging依賴。一旦你在Spring內(nèi)部使用了日志調(diào)用,Spring會(huì)將日志調(diào)用變?yōu)檎{(diào)用SLF4J API,如果你應(yīng)用中其它的庫(kù)調(diào)用了那個(gè)API,你將有一個(gè)單獨(dú)的地方配置和管理日志。

A common choice might be to bridge Spring to SLF4J, and then provide explicit binding from SLF4J to Log4J. You need to supply 4 dependencies (and exclude the existing commons-logging): the bridge, the SLF4J API, the binding to Log4J, and the Log4J implementation itself. In Maven you would do that like this

一個(gè)常用的選擇連接Spring和SLF4J,然后提供SLF4J到Log4J的顯式綁定。你需要提供四個(gè)依賴(排除現(xiàn)有的commons-logging):連接、SLF4J API、到Log4J的綁定、Log4J本身的實(shí)現(xiàn)。在Maven中你可能這么做:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.0.0.BUILD-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.14</version>
    </dependency>
</dependencies>

That might seem like a lot of dependencies just to get some logging. Well it is, but it is optional, and it should behave better than the vanilla commons-logging with respect to classloader issues, notably if you are in a strict container like an OSGi platform. Allegedly there is also a performance benefit because the bindings are at compile-time not runtime.

這可能看起來(lái)為了得到一些日志需要很多依賴。還好它是可選的,比起commons-logging的關(guān)于類加載器的問(wèn)題,尤其是你在一個(gè)像OSGi平臺(tái)那樣嚴(yán)格的容器中的時(shí)候,它應(yīng)該更好操作。據(jù)說(shuō)這兒也有一個(gè)性能提升,因?yàn)榻壎ㄊ窃诰幾g時(shí)而不是在運(yùn)行時(shí)。

A more common choice amongst SLF4J users, which uses fewer steps and generates fewer dependencies, is to bind directly to Logback. This removes the extra binding step because Logback implements SLF4J directly, so you only need to depend on two libraries not four ( jcl-over-slf4j and logback). If you do that you might also need to exclude the slf4j-api dependency from other external dependencies (not Spring), because you only want one version of that API on the classpath.

在SLF4J用戶中,一個(gè)更通用的選擇是直接綁定到Logback,這樣使用步驟更少且依賴也更少。這去除了外部綁定步驟,因?yàn)長(zhǎng)ogback直接實(shí)現(xiàn)了SLF4J,因此你僅需要依賴兩個(gè)庫(kù)而不是四個(gè)(jcl-over-slf4jlogback)。如果你這樣做的話你可能也需要從其它的外部應(yīng)用中(不是從Spring)排除slf4j-api依賴,因?yàn)槟阍赾lasspath中僅需要一個(gè)版本的API。

Using Log4J

Many people use Log4j as a logging framework for configuration and management purposes. It’s efficient and well-established, and in fact it’s what we use at runtime when we build and test Spring. Spring also provides some utilities for configuring and initializing Log4j, so it has an optional compile-time dependency on Log4j in some modules.

許多人使用Log4j作為配置和管理的日志框架。它有效且完善的,當(dāng)我們構(gòu)建和測(cè)試Spring時(shí),實(shí)際上這就是在運(yùn)行時(shí)我們使用的東西。Spring也提供一些配置和初始化Log4j的工具,因此在某些模塊有可選的Log4j的編譯時(shí)依賴。

To make Log4j work with the default JCL dependency (commons-logging) all you need to do is put Log4j on the classpath, and provide it with a configuration file ( log4j.properties or log4j.xml in the root of the classpath). So for Maven users this is your dependency declaration:

為了使Log4j能與默認(rèn)的JCL依賴(commons-logging)一起工作,所有你需要做的是把Log4j放到classpath中,并提供一個(gè)配置文件(log4j.propertieslog4j.xml在classpath的根目錄)。對(duì)于Maven用戶依賴聲明如下:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.0.0.BUILD-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.14</version>
    </dependency>
</dependencies>

And here’s a sample log4j.properties for logging to the console:

下面是一個(gè)log4j.properties輸出日志到控制臺(tái)的樣本:

image

Runtime Containers with Native JCL

Many people run their Spring applications in a container that itself provides an implementation of JCL. IBM Websphere Application Server (WAS) is the archetype. This often causes problems, and unfortunately there is no silver bullet solution; simply excluding commons-logging from your application is not enough in most situations.

許多人在容器中運(yùn)行他們的Spring應(yīng)用,容器本身提供了一個(gè)JCL實(shí)現(xiàn)。IBM Websphere Application Server (WAS) 是原型。這經(jīng)常會(huì)引起問(wèn)題,不幸的是沒(méi)有一勞永逸的解決方案;在大多數(shù)環(huán)境下簡(jiǎn)單的執(zhí)行commons-logging是不夠的。

To be clear about this: the problems reported are usually not with JCL per se, or even with commons-logging: rather they are to do with binding commons-logging to another framework (often Log4J). This can fail because commons-logging changed the way they do the runtime discovery in between the older versions (1.0) found in some containers and the modern versions that most people use now (1.1). Spring does not use any unusual parts of the JCL API, so nothing breaks there, but as soon as Spring or your application tries to do any logging you can find that the bindings to Log4J are not working.

為了使這個(gè)更清楚:報(bào)告的問(wèn)題本質(zhì)上一般不是關(guān)于JCL的,或關(guān)于commons-logging的:而是他們?nèi)ソ壎?code>commons-logging到其它的框架上(通常是Log4j)。這可能會(huì)失敗因?yàn)?code>commons-logging在一些容器的舊版本(1.0)和大多數(shù)人使用的現(xiàn)代版本(1.1)中改變了運(yùn)行時(shí)發(fā)現(xiàn)方式。Spring不使用JCL API的和任何不常用的部分,因此不會(huì)有問(wèn)題出現(xiàn),但是一旦Spring或你的應(yīng)用試圖去輸出日志,你可能發(fā)現(xiàn)到Log4j的綁定是不起作用的。

In such cases with WAS the easiest thing to do is to invert the class loader hierarchy (IBM calls it "parent last") so that the application controls the JCL dependency, not the container. That option isn’t always open, but there are plenty of other suggestions in the public domain for alternative approaches, and your mileage may vary depending on the exact version and feature set of the container.

在這種情況下使用WAS最容易做的事是逆轉(zhuǎn)類加載層(IBM稱為"parent last"),為的是應(yīng)用能控制依賴,而不是容器。雖然這種選擇并非總是公開(kāi)的,但在公共領(lǐng)域?qū)τ谔娲椒ㄓ性S多其它的建議,你的解決這個(gè)問(wèn)題花的時(shí)間可能是不同的,這取決于確定的版本和容器集合的特性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

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