Spring源碼探究:容器

結(jié)合源碼分析 Spring 容器與 SpringMVC 容器之間的關(guān)系

問(wèn)題

問(wèn)題描述:項(xiàng)目中發(fā)現(xiàn)玖像,自定義切面注解在 Controller 層正常工作诀拭,在 Service 層卻無(wú)法正常工作稠鼻。為了便于分析捺信,去掉代碼中的業(yè)務(wù)邏輯,只留下場(chǎng)景仁烹。

自定義注解耸弄,打印時(shí)間

/**

* Description: 自定義打印時(shí)間的注解

* Created by jiangwang3 on 2018/5/9.

*/

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

@Documented

public @interface PrintTime {

}

注解解析器

/**

*Description:打印時(shí)間注解的解析器

* @author jiangwang

* @date 11:28 2018/5/14

*/

@Aspect

public class PrintTimeProcessor {

? ? private Logger LOGGER = LoggerFactory.getLogger(getClass());

? ? @Pointcut("@annotation(com.foo.service.annotation.PrintTime)")

? ? public void printTimePoint() {

? ? }

? ? @Around("printTimePoint()")

? ? public Object process(ProceedingJoinPoint jp) throws Throwable{

? ? ? ? System.out.println();

? ? ? ? LOGGER.error("開(kāi)始運(yùn)行程序。卓缰。计呈。Start==>");

? ? ? ? Object proceed = jp.proceed();

? ? ? ? LOGGER.error("結(jié)束啦,運(yùn)行結(jié)束==>");

? ? ? ? System.out.println();

? ? ? ? return proceed;

? ? }

}

Controller層

/**

* @author jiangwang

* @date? 2018/5/14

*/

@RestController

@RequestMapping(value = "/user")

public class UserController {

? ? private Logger logger = LoggerFactory.getLogger(getClass());

? ? @Resource

? ? private UserService userService;

? ? @RequestMapping(value = "/serviceAspect", method={RequestMethod.GET})

? ? public? String serviceAspect(){

? ? ? ? return userService.serviceAspect();

? ? }

? ? @RequestMapping(value = "/controllerAspect", method={RequestMethod.GET})

? ? @PrintTime

? ? public? String name(){

? ? ? ? logger.info("Controller層----測(cè)試切面");

? ? ? ? return "controllerAspect";

? ? }

}

Service層

/**

* @author jiangwang

* @date 11:34 2018/5/14

*/

@Service

public class UserService {

? ? private Logger logger = LoggerFactory.getLogger(getClass())

? ? @PrintTime

? ? public String serviceAspect(){

? ? ? ? logger.info("Service層---測(cè)試切面");

? ? ? ? return "serviceAspect";

? ? }

}

spring.xml 配置文件征唬,主要部分

<context:annotation-config />

<!-- 動(dòng)態(tài)代理開(kāi)啟 -->

<aop:aspectj-autoproxy proxy-target-class="true" />

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

? ? <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

</context:component-scan>

<!-- 公共配置引入 -->

<import resource="classpath:spring/spring-config-dao.xml" />

springmvc.xml 配置文件捌显,主要部分

<mvc:annotation-driven />

<mvc:default-servlet-handler />

<!-- 動(dòng)態(tài)代理開(kāi)啟 -->

<aop:aspectj-autoproxy proxy-target-class="true" />

<!-- mvc controller -->

<context:component-scan base-package="com.foo.web.controller" use-default-filters="false">

? ? <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

? ? <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />

</context:component-scan>

<bean class="com.foo.service.processor.PrintTimeProcessor"/>

以上為主要代碼。項(xiàng)目運(yùn)行之后总寒,發(fā)現(xiàn)在 Service 層的注解切面未生效扶歪,而在 Controller 層正常。而當(dāng)我將 springmvc.xml 中的

<bean class="com.foo.service.processor.PrintTimeProcessor"/>

遷移至 spring.xml 中摄闸,發(fā)現(xiàn) Service 層與 Controller 層的注解切面均可正常運(yùn)行善镰。WHY???

從源碼的角度探究該問(wèn)題

由于源碼中的方法較長(zhǎng),所以只貼出重點(diǎn)且與主題相關(guān)的代碼贪薪。建議結(jié)合本地源碼一起看媳禁。

為了說(shuō)清楚這個(gè)問(wèn)題眠副,咱們先看一下Spring容器是如何實(shí)現(xiàn) Bean 自動(dòng)注入(簡(jiǎn)化版)

Web 項(xiàng)目的入口是 web.xml画切,所以咱們從它開(kāi)始。

web.xml 配置文件囱怕,主要部分

<!-- Spring Config -->

<listener>

? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<context-param>

? <param-name>contextConfigLocation</param-name>

? <param-value>classpath:spring/spring-config.xml</param-value>

</context-param>

<!-- SpringMvc Config -->

<servlet>

? <servlet-name>springMvc</servlet-name>

? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

? <init-param>

? ? <param-name>contextConfigLocation</param-name>

? ? <param-value>classpath:spring/spring-mvc.xml</param-value>

? </init-param>

? <load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

? <servlet-name>springMvc</servlet-name>

? <url-pattern>/*</url-pattern>

</servlet-mapping>

Spring 容器 Bean 加載流程

從 Spring 配置部分可以看出霍弹,ContextLoaderListener 監(jiān)聽(tīng)器是 Spring 容器的入口,進(jìn)入該文件:

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {

? ? public ContextLoaderListener() {

? ? }

? ? public ContextLoaderListener(WebApplicationContext context) {

? ? ? ? super(context);

? ? }

? ? @Override

? ? public void contextInitialized(ServletContextEvent event) {

? ? ? ? initWebApplicationContext(event.getServletContext());

? ? }

? ? @Override

? ? public void contextDestroyed(ServletContextEvent event) {

? ? ? ? closeWebApplicationContext(event.getServletContext());

? ? ? ? ContextCleanupListener.cleanupAttributes(event.getServletContext());

? ? }

}

ContextLoaderListener?監(jiān)聽(tīng)器一共有四個(gè)方法娃弓,可以很容易地判斷出來(lái)典格,進(jìn)入該監(jiān)聽(tīng)器后,會(huì)進(jìn)入初始化方法:contextInitialized台丛。繼而進(jìn)入initWebApplicationContext?方法耍缴,方法注釋中“Initialize Spring’s web application context for the given servlet context”砾肺,明確表明了該方法的目的是初始化 Spring Web 應(yīng)用。這段代碼中有兩句話(huà)比較關(guān)鍵:

this.context = createWebApplicationContext(servletContext);

創(chuàng)建 Web 應(yīng)用容器防嗡,即創(chuàng)建了 Spring 容器变汪;

configureAndRefreshWebApplicationContext(cwac, servletContext);

配置并刷新Spring容器。后續(xù)發(fā)生的所有事蚁趁,都是從它開(kāi)始的裙盾。進(jìn)入,里面的重點(diǎn)代碼是:

wac.refresh();

refresh()?方法是spring容器注入bean的核心方法他嫡,每一行代碼都很重要番官。代碼結(jié)構(gòu)也非常優(yōu)美,每一行代碼背后都完成了一件事钢属,代碼結(jié)構(gòu)比較容易理解徘熔。由于內(nèi)容較多,只講里面跟主題相關(guān)的兩句話(huà):

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

獲取 Bean 工廠淆党,把你配置文件中的內(nèi)容近顷,放在 Bean 工廠中,留著后面創(chuàng)建 Bean 時(shí)用宁否。

finishBeanFactoryInitialization(beanFactory);

開(kāi)始創(chuàng)建 Bean窒升,即實(shí)現(xiàn) Spring 中的自動(dòng)注入功能。進(jìn)入該方法后慕匠,末尾有這么一句話(huà):

beanFactory.preInstantiateSingletons();

繼續(xù)跟進(jìn)饱须,貼出該方法中的重點(diǎn)代碼:

getBean(beanName);

我們?cè)?preInstantiateSingletons() 方法中,會(huì)發(fā)現(xiàn)有多個(gè)地方出現(xiàn)了 getBean() 方法台谊,究竟咱們貼出來(lái)的是哪一句蓉媳?無(wú)關(guān)緊要确徙。跟進(jìn)去之后影锈,

@Override

public Object getBean(String name) throws BeansException {

? ? return doGetBean(name, null, null, false);

}

這里調(diào)用了 doGetBean() 方法兽埃,Spring 中只要以do?命名的方法矫渔,都是真正干活的洲愤。重點(diǎn)代碼分段貼出分析:

// Eagerly check singleton cache for manually registered singletons.

Object sharedInstance = getSingleton(beanName);

if (sharedInstance != null && args == null) {

? ? if (logger.isDebugEnabled()) {

? ? ? ? if (isSingletonCurrentlyInCreation(beanName)) {

? ? ? ? ? ? logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +

? ? ? ? ? ? ? ? ? ? "' that is not fully initialized yet - a consequence of a circular reference");

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? logger.debug("Returning cached instance of singleton bean '" + beanName + "'");

? ? ? ? }

? ? }

? ? bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

}

直接獲取單例 Bean宰闰,若沒(méi)有取到辛块,繼續(xù)往下走:

// Check if bean definition exists in this factory.

BeanFactory parentBeanFactory = getParentBeanFactory();

if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

? ? // Not found -> check parent.

? ? String nameToLookup = originalBeanName(name);

? ? if (args != null) {

? ? ? ? // Delegation to parent with explicit args.

? ? ? ? return (T) parentBeanFactory.getBean(nameToLookup, args);

? ? }

? ? else {

? ? ? ? // No args -> delegate to standard getBean method.

? ? ? ? return parentBeanFactory.getBean(nameToLookup, requiredType);

? ? }

}

這一段代碼單獨(dú)看浊猾,不知所云贼邓,里面提到了一個(gè)詞:Parent阶冈。暫且跳過(guò),后續(xù)會(huì)回來(lái)分析這一段塑径。繼續(xù):

// Create bean instance.

if (mbd.isSingleton()) {

? ? ? sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public Object getObject() throws BeansException {

? ? ? ? ? ? ? ? try {

? ? ? ? ? ? ? ? ? ? return createBean(beanName, mbd, args);

? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? catch (BeansException ex) {

? ? ? ? ? ? ? ? ? ? ? // Explicitly remove instance from singleton cache: It might have been put there

? ? ? ? ? ? ? ? ? ? ? // eagerly by the creation process, to allow for circular reference resolution.

? ? ? ? ? ? ? ? ? ? ? // Also remove any beans that received a temporary reference to the bean.

? ? ? ? ? ? ? ? ? ? ? destroySingleton(beanName);

? ? ? ? ? ? ? ? ? ? ? throw ex;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? });

? ? ? ? bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

}

這段代碼中有 createBean女坑,咱們的目的是分析 Bean 的創(chuàng)建過(guò)程,此處出現(xiàn)了create统舀,毫不猶豫地跟進(jìn)匆骗,進(jìn)入實(shí)現(xiàn)類(lèi)中的方法劳景,有這么一句:

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

剛才咱們提了,Spring 中有do?命名的方法碉就,是真正干活的枢泰。跟進(jìn):

instanceWrapper = createBeanInstance(beanName, mbd, args);

這句話(huà)是初始化 Bean,即創(chuàng)建了?Bean铝噩,等價(jià)于調(diào)用了一個(gè)類(lèi)的空構(gòu)造方法衡蚂。此時(shí),已經(jīng)成功地創(chuàng)建了對(duì)象骏庸,下文需要做的是毛甲,給該對(duì)象注入需要的屬性;

populateBean(beanName, mbd, instanceWrapper);

填充?Bean 屬性具被,就是剛才咱們提的玻募,初始化一個(gè)對(duì)象后,只是一個(gè)空對(duì)象一姿,需要給它填充屬性七咧。跟進(jìn),看 Spring 是如何為對(duì)象注入屬性的叮叹,或者說(shuō)艾栋,看一下 Spring 是如何實(shí)現(xiàn) Bean 屬性的自動(dòng)注入:

pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

繼續(xù)進(jìn)入 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues 方法:

metadata.inject(bean, beanName, pvs);

這句話(huà)中,出現(xiàn)了inject蛉顽,這個(gè)詞的意思是“注入”蝗砾。咱們可以斷定,Spring 的自動(dòng)注入携冤,八成跟它有關(guān)了悼粮。進(jìn)入該方法:

<code>element.inject(target, beanName, pvs); </code>

與上一句一樣,只是做了一些參數(shù)處理曾棕,并沒(méi)有開(kāi)始注入扣猫。繼續(xù)跟進(jìn)看:

Field field = (Field) this.member;

ReflectionUtils.makeAccessible(field);

field.set(target, getResourceToInject(target, requestingBeanName));

看到這里,大概明白了 Spring 是如何自動(dòng)注入了翘地。Java 反射相關(guān)的代碼申尤,通過(guò)反射的方式給 field 賦值。這里的field?是 Bean 中的某一個(gè)屬性子眶,例如咱們開(kāi)始時(shí)的 UserController 類(lèi)中的userService瀑凝。getResourceToInject序芦,獲取需要賦予的值了臭杰,其實(shí)這里會(huì)重新進(jìn)入 getBean 方法,獲取 Bean 值(例如 UserController 對(duì)象中需要注入 userService谚中。)渴杆,然后賦予 field寥枝。至此,Spring容器已經(jīng)初始化完成磁奖,Spring Bean注入的大概流程囊拜,咱們也已經(jīng)熟悉了”却睿回到開(kāi)始初始化 Spring 容器的地方冠跷,ContextLoader 類(lèi) initWebApplicationContext 方法,

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

初始化 Spring 容器之后身诺,將其放入了 servletContext 中蜜托。

咱們的問(wèn)題是,“在項(xiàng)目中霉赡,自定義切面注解在 Controller 層正常工作橄务,卻在 Service 層無(wú)法正常工作?”看完這個(gè)穴亏,其實(shí)并沒(méi)有解答該問(wèn)題蜂挪,咱們下面繼續(xù)看 SpringMVC Bean的加載流程,看完 SpringMVC 后嗓化,答案會(huì)自動(dòng)浮出水面棠涮。

SpringMVC 容器 Bean 加載流程

同樣,從 web.xml 中的?SpringMVC 配置出發(fā)刺覆,里面有 DispatcherServlet故爵,這是 SpringMVC 的入口,跟進(jìn)之后發(fā)現(xiàn)方法較多隅津,無(wú)法知道會(huì)執(zhí)行哪個(gè)方法诬垂。但是咱們要記住,DispatcherServlet?本質(zhì)上是一個(gè)?Servlet伦仍,通過(guò)它的繼承關(guān)系圖也可以證明:


DispatcherServlet繼承關(guān)系圖

看一下 Servlet 的接口:

public interface Servlet {

? ? public void init(ServletConfig config) throws ServletException;

? ? public ServletConfig getServletConfig();

? ? public void service(ServletRequest req, ServletResponse res)

? ? ? ? ? ? throws ServletException, IOException;

? ? public String getServletInfo();

? ? public void destroy();

}

從 Servlet 接口方法中可以看出结窘,Servlet 的入口是init?方法,層層跟進(jìn)(一定要根據(jù) DispatcherServlet 繼承圖跟進(jìn))充蓝,進(jìn)入到了 FrameworkServlet 的initServletBean()?方法隧枫,進(jìn)入方法,貼出重點(diǎn)代碼:

this.webApplicationContext = initWebApplicationContext();

字面理解谓苟,初始化?SpringMVC Web容器官脓,進(jìn)入探究:

WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

前面咱們提到,Spring 容器初始化完成之后涝焙,放入了servletContext?中卑笨。這里又從 servletContext 獲取到了Spring 容器

wac = createWebApplicationContext(rootContext);

字面理解創(chuàng)建 Web 應(yīng)用容器仑撞,且參數(shù)是 Spring 容器赤兴。跟進(jìn)方法:

ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

創(chuàng)建web應(yīng)用容器妖滔,即咱們所理解的?SpringMVC容器在此創(chuàng)建了;

wac.setParent(parent);

這里是重點(diǎn)桶良,SpringMVC?容器將 Spring 容器設(shè)置成了自己的父容器座舍。

configureAndRefreshWebApplicationContext(wac);

這個(gè)方法剛才在分析 Spring Bean 加載流程時(shí),分析過(guò)了陨帆。其中有一段曲秉,前面說(shuō),“暫且跳過(guò)疲牵,后續(xù)會(huì)回來(lái)分析這一段”“痘耄現(xiàn)在開(kāi)始分析:

在 AbstractBeanFactory 類(lèi) doGetBean 方法,有這么一段:

// Check if bean definition exists in this factory.

BeanFactory parentBeanFactory = getParentBeanFactory();

if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

? ? // Not found -> check parent.

? ? String nameToLookup = originalBeanName(name);

? ? if (args != null) {

? ? ? ? ? ? // Delegation to parent with explicit args.

? ? ? ? return (T) parentBeanFactory.getBean(nameToLookup, args);

? ? }

? ? else {

? ? ? ? // No args -> delegate to standard getBean method.

? ? ? ? return parentBeanFactory.getBean(nameToLookup, requiredType);

? ? }

}

這里其實(shí)是在獲取父容器中的 Bean瑰步,若獲取到矢洲,直接拿到 Bean,這個(gè)方法就結(jié)束了缩焦。結(jié)論:子容器可以使用父容器里的 Bean读虏,反之則不行。

現(xiàn)在來(lái)解答咱們的問(wèn)題

<bean class="com.foo.service.processor.PrintTimeProcessor"/>

當(dāng)上門(mén)這句話(huà)放在 springmvc.xml 中時(shí)袁滥,名為“printTimeProcessor”?的 Bean 會(huì)存在于 SpringMVC 容器盖桥,那么 Spring 容器是無(wú)法獲取它的。而 Service 層恰巧是存在于 Spring 容器中题翻,所以“printTimeProcessor”?切面對(duì) Service 層不起作用揩徊。而 Controller 層本身存在于 SpringMVC 容器,所以 Controller 層可以正常工作嵌赠。而當(dāng)它放在 spring.xml 中時(shí)塑荒,”printTimeProcessor” 是存在于 Spring 容器中,SpringMVC 容器是 Spring 容器的子容器姜挺,子容器可以獲取到父容器的 Bean齿税,所以 Controller 層與 Service 層都能獲取到該 Bean,所有都能正常使用它炊豪。

歡迎工作一到五年的Java工程師朋友們加入Java程序員開(kāi)發(fā): 854393687

群內(nèi)提供免費(fèi)的Java架構(gòu)學(xué)習(xí)資料(里面有高可用凌箕、高并發(fā)、高性能及分布式词渤、Jvm性能調(diào)優(yōu)牵舱、Spring源碼,MyBatis缺虐,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個(gè)知識(shí)點(diǎn)的架構(gòu)資料)合理利用自己每一分每一秒的時(shí)間來(lái)學(xué)習(xí)提升自己芜壁,不要再用"沒(méi)有時(shí)間“來(lái)掩飾自己思想上的懶惰!趁年輕,使勁拼沿盅,給未來(lái)的自己一個(gè)交代把篓!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纫溃,一起剝皮案震驚了整個(gè)濱河市腰涧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌紊浩,老刑警劉巖窖铡,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坊谁,居然都是意外死亡费彼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)口芍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)箍铲,“玉大人,你說(shuō)我怎么就攤上這事鬓椭〉吆铮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵小染,是天一觀的道長(zhǎng)翘瓮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)裤翩,這世上最難降的妖魔是什么资盅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮踊赠,結(jié)果婚禮上呵扛,老公的妹妹穿的比我還像新娘。我一直安慰自己筐带,他們只是感情好择份,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著烫堤,像睡著了一般荣赶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鸽斟,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天拔创,我揣著相機(jī)與錄音,去河邊找鬼富蓄。 笑死剩燥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灭红,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侣滩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了变擒?” 一聲冷哼從身側(cè)響起君珠,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎娇斑,沒(méi)想到半個(gè)月后策添,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毫缆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年唯竹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苦丁。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浸颓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旺拉,到底是詐尸還是另有隱情产上,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布账阻,位于F島的核電站蒂秘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淘太。R本人自食惡果不足惜姻僧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蒲牧。 院中可真熱鬧撇贺,春花似錦、人聲如沸冰抢。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挎扰。三九已至翠订,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遵倦,已是汗流浹背尽超。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梧躺,地道東北人似谁。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親巩踏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秃诵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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

  • 結(jié)合源碼分析Spring容器與Springmvc容器之間的關(guān)系 問(wèn)題 問(wèn)題描述:項(xiàng)目中發(fā)現(xiàn),自定義切面注解在Con...
    Fooisart閱讀 1,348評(píng)論 6 9
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書(shū)筆記塞琼,整理的知識(shí)點(diǎn)菠净,也是為了防止忘記,尊重勞動(dòng)成果屈梁,轉(zhuǎn)載注明出處哦嗤练!如果你也喜歡榛了,那...
    波波波先森閱讀 12,294評(píng)論 6 86
  • org.springframework.beans: org.springframework.beans.fact...
    過(guò)河卒sc閱讀 590評(píng)論 1 1
  • 劉志宇/文 清晨的第一縷陽(yáng)光照射入營(yíng)地在讶,戶(hù)外露營(yíng)又增添了一股火紅的色彩。眺望遠(yuǎn)方若隱若現(xiàn)的綺麗景色霜大,一座高山隱現(xiàn)出...
    Oneworld閱讀 430評(píng)論 0 0
  • 現(xiàn)在遍布網(wǎng)絡(luò)的寫(xiě)作,閱讀途茫,運(yùn)動(dòng)碟嘴,早起,幾乎成了全民的口頭禪囊卜。我想到不知誰(shuí)說(shuō)過(guò)的一句話(huà)娜扇,人類(lèi)一思考,上帝就發(fā)笑栅组,套...
    Andy_流沙閱讀 210評(píng)論 0 1