Spring Boot启动过程源码分析

Spring Boot启动过程

1. 创建SpringApplication实例

    构造函数调用initialize

会通过SpringFactoriesLoader.loadFactoryNames(type, classLoader),扫描当前Class所在的工程内所有的 ApplicationContextInitializer和ApplicationListener

加载的ApplicationListener:

org.springframework.boot.ClearCachesApplicationListener@2f4948e4

org.springframework.boot.builder.ParentContextCloserApplicationListener@1f2586d6

org.springframework.boot.context.FileEncodingApplicationListener@10683d9d

org.springframework.boot.context.config.AnsiOutputApplicationListener@3fc2959f

org.springframework.boot.context.config.ConfigFileApplicationListener@5aa9e4eb

org.springframework.boot.context.config.DelegatingApplicationListener@6989da5e

org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener@385c9627

org.springframework.boot.logging.ClasspathLoggingApplicationListener@139982de

org.springframework.boot.logging.LoggingApplicationListener@682b2fa

org.springframework.boot.autoconfigure.BackgroundPreinitializer@217ed35e

org.springframework.boot.devtools.restart.RestartApplicationListener@7dcf94f8

同时判断main class和是否是webEnvironment

2.进入SpringApplication.run方法

run方法主要步骤:

1):活动SpringApplicationRunListerns,

SpringApplicationRunListeners listeners = getRunListeners(args);

listeners.starting();

这里得到一个org.springframework.boot.context.event.EventPublishingRunListener

2)启动listeners

EventPublishingRunListener会广播Application start event, 其中RestartApplicationListener对spring application进行重启

Restarter.instance是一个静态变量,如果已经重启,就不再重启

3)创建并准备ConfigurableEnvironment environment

4)创建ConfigurableApplicationContext context

首先通过Class.forName是否能加载,来检测是否是web环境,根据结果创建不同的conext,如果是web,则创建AnnotationConfigEmbeddedWebApplicationContext

在构建AnnotationConfigEmbeddedWebApplicationContext时,会初始化BeanDefinitionReader和

它会把一些PostProcessor 的beanDefintion注册进context,其中重要的是ConfigurationClassPostProcessor,注册名字为:org.springframework.context.annotation.internalConfigurationAnnotationProcessor

ConfigurationClassPostProcessor implments BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor

此post processor会loadBeanDinfinitions 并注册到Context

AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor extends BeanPostProcssor

它是BeanPostProcessor,会把Autowired的自动进行填充。

public AnnotationConfigEmbeddedWebApplicationContext() {

this.reader = new AnnotatedBeanDefinitionReader(this);

this.scanner = new ClassPathBeanDefinitionScanner(this);

}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

Assert.notNull(environment, "Environment must not be null");

this.registry = registry;

this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

}

AnnotationConfigUtils::

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(

BeanDefinitionRegistry registry, Object source) {

DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);

if (beanFactory != null) {

if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {

beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

}

if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {

beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

}

}

Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

}

if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

}

if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

}

// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.

if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));

}

// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.

if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition();

try {

def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,

AnnotationConfigUtils.class.getClassLoader()));

}

catch (ClassNotFoundException ex) {

throw new IllegalStateException(

"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);

}

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));

}

if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));

}

if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {

RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));

}

return beanDefs;

}

5) 对context进行准备

主要包括:

setEnviroment,

applyInitializers:

  1 ConfigurationWarningsApplicationContextInitializer

context.addBeanFactoryPostProcessor(

new ConfigurationWarningsPostProcessor(getChecks()));

2 SharedMetadataReaderFactoryContextInitializer:: addBeanFactoryPostProcessor(CachingMetadataReaderFactoryPostProcessor)


3.AutoConfigurationReportLoggingInitializer

    public void initialize(ConfigurableApplicationContext applicationContext) {

this.applicationContext = applicationContext;

applicationContext.addApplicationListener(new AutoConfigurationReportListener());

if (applicationContext instanceof GenericApplicationContext) {

// Get the report early in case the context fails to load

this.report = ConditionEvaluationReport

.get(this.applicationContext.getBeanFactory());

}

}

4.RestartScopeInitializer

applicationContext.getBeanFactory().registerScope("restart", new RestartScope());

loadContext:

6) refreshContext, 调用AbsractApplicationContext的模版方法:

public ConfigurableApplicationContext run(String... args) {

StopWatch stopWatch = new StopWatch();

stopWatch.start();

ConfigurableApplicationContext context = null;

FailureAnalyzers analyzers = null;

configureHeadlessProperty();

SpringApplicationRunListeners listeners = getRunListeners(args);

listeners.starting();

try {

ApplicationArguments applicationArguments = new DefaultApplicationArguments(

args);

ConfigurableEnvironment environment = prepareEnvironment(listeners,

applicationArguments);

Banner printedBanner = printBanner(environment);

context = createApplicationContext();

analyzers = new FailureAnalyzers(context);

prepareContext(context, environment, listeners, applicationArguments,

printedBanner);

refreshContext(context);

afterRefresh(context, applicationArguments);

listeners.finished(context, null);

stopWatch.stop();

if (this.logStartupInfo) {

new StartupInfoLogger(this.mainApplicationClass)

.logStarted(getApplicationLog(), stopWatch);

}

return context;

}

catch (Throwable ex) {

handleRunFailure(context, listeners, analyzers, ex);

throw new IllegalStateException(ex);

}

}

这里会进入super.refresh

AbstractApplicationContext.refresh

1. prepareRefresh

2.获得 beanFactory

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

得到DefaultListableBeanFactory

3.对BeanFactory进行准备

prepareBeanFactory(beanFactory);

  主要做以下事情:

注册ApplicationContextAwareProcessor,它主要处理各种Aware接口

注册ApplicationListenerDetector

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

// Tell the internal bean factory to use the context's class loader etc.

beanFactory.setBeanClassLoader(getClassLoader());

beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);

beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);

beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);

beanFactory.ignoreDependencyInterface(MessageSourceAware.class);

beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// BeanFactory interface not registered as resolvable type in a plain factory.

// MessageSource registered (and found for autowiring) as a bean.

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);

beanFactory.registerResolvableDependency(ResourceLoader.class, this);

beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);

beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.

if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {

beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

// Set a temporary ClassLoader for type matching.

beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));

}

// Register default environment beans.

if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {

beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());

}

if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {

beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());

}

if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {

beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());

}

}

4.postProcessBeanFactory,主要给机会在标准初始化之后对beanFactory进行修改

    Modify the application context's internal bean factory after its standard

* initialization. All bean definitions will have been loaded, but no beans

* will have been instantiated yet. This allows for registering special

* BeanPostProcessors etc in certain ApplicationContext implementations.

这里主要注册了一个WebApplicationContextServletContextAwareProcessor

如果有basePackages,则进行扫描注册basePackage所包含的bean definition

AnnotationConfigEmbeddedWebApplicationContext::

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

super.postProcessBeanFactory(beanFactory);

if (this.basePackages != null && this.basePackages.length > 0) {

this.scanner.scan(this.basePackages);

}

if (this.annotatedClasses != null && this.annotatedClasses.length > 0) {

this.reader.register(this.annotatedClasses);

}

}

super: EmbeddedWebApplicationContext

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

beanFactory.addBeanPostProcessor(

new WebApplicationContextServletContextAwareProcessor(this));

beanFactory.ignoreDependencyInterface(ServletContextAware.class);

}

5. invokeBeanFactoryPostProcessors


调用父类AbstractApplicationContext的方法invokeBeanFactoryPostProcessors. 主要有三个BeanFactoryPostProcssor

// Invoke factory processors registered as beans in the context.

invokeBeanFactoryPostProcessors(beanFactory);

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime

// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)

if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {

beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));

}

}

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 的主要逻辑

1. 处理传进去的 beanFactoryPostProcessors

for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {

if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {

BeanDefinitionRegistryPostProcessor registryPostProcessor =

(BeanDefinitionRegistryPostProcessor) postProcessor;

registryPostProcessor.postProcessBeanDefinitionRegistry(registry);

registryPostProcessors.add(registryPostProcessor);

}

else {

regularPostProcessors.add(postProcessor);

}

}

2. 从已经注册的BeanDefinition中找到所有BeanDefinitionRegistryPostProcessor(它是BeanFactoryPostProcessor的子类),这里会找到ConfigurationClassPostProcessor

String[] postProcessorNames =

beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

之后分三次对这些processor进行处理,先处理PriorityOrdered,之后处理Ordered,最后处理普通的。处理之前会对其processor进行Bean化

List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

for (String ppName : postProcessorNames) {

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

sortPostProcessors(beanFactory, priorityOrderedPostProcessors);

registryPostProcessors.addAll(priorityOrderedPostProcessors);

invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

处理ConfigurationClassPostProcessor时,会加载Application类所在的工程的BeanDefinition,会加载工程内jar的bean definition(通过DeferedImportSelector)

(后面详细分析ConfigurationClassPostProcessor处理主要逻辑)

  3. 处理BeanFactoryPostProcessor, ConfigurationClassPostProcessor也是BeanFactory postProcessor

这里会对Configuration class进行cglib enhace

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.

invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);

nvokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

/**

* Prepare the Configuration classes for servicing bean requests at runtime

* by replacing them with CGLIB-enhanced subclasses.

*/

@Override

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

int factoryId = System.identityHashCode(beanFactory);

if (this.factoriesPostProcessed.contains(factoryId)) {

throw new IllegalStateException(

"postProcessBeanFactory already called on this post-processor against " + beanFactory);

}

this.factoriesPostProcessed.add(factoryId);

if (!this.registriesPostProcessed.contains(factoryId)) {

// BeanDefinitionRegistryPostProcessor hook apparently not supported...

// Simply call processConfigurationClasses lazily at this point then.

processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);

}

                //对configuration class生成cglib 代理,更新 beanDefinitionMap

enhanceConfigurationClasses(beanFactory);

beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));

}

  ConfigurationClassPostProcessor的处理流程

    1)从注册的bean中得到Configuration class, 这里只有Application这个是Configuration class


创建ConfigurationClassParser

public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory,

ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader,

BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {

this.metadataReaderFactory = metadataReaderFactory;

this.problemReporter = problemReporter;

this.environment = environment;

this.resourceLoader = resourceLoader;

this.registry = registry;

this.componentScanParser = new ComponentScanAnnotationParser(

environment, resourceLoader, componentScanBeanNameGenerator, registry);

this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);

}

2)ConfigurationClassParser .processConfigurationClass,

    SourceClass sourceClass = asSourceClass(configClass);

do {

sourceClass = doProcessConfigurationClass(configClass, sourceClass);

}

while (sourceClass != null);

doProcessConfigurationClass 主要逻辑:

            1    // Recursively process any member (nested) classes first

processMemberClasses(configClass, sourceClass);

            2.  // Process any @PropertySource annotations

                processPropertySource(propertySource);

          3. // Process any @ComponentScan annotations

Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(

sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

                    扫描base package获得所有的beanDefinition, 之后检查这些BeanDefinition是否有Configuration class,如果是Configuration class则递归处理,

这里@Component, @CompentScan, @Import被认为是lite Configuration

                        // The config class is annotated with @ComponentScan -> perform the scan immediately

Set<BeanDefinitionHolder> scannedBeanDefinitions =

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

// Check the set of scanned definitions for any further config classes and parse recursively if needed

for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

if (ConfigurationClassUtils.checkConfigurationClassCandidate(

holder.getBeanDefinition(), this.metadataReaderFactory)) {

parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());

}

}

          4. // Process any @Import annotations

          5. // Process any @ImportResource annotations

        6. // Process individual @Bean methods

          7. // Process superclass, if any

          8. // No superclass -> processing is complete

其中每个过程都是一个递归调用

3)处理importSelector, 这里的importSelector是EnableAutoConfiuration的Annotation里@Import(EnableAutoConfigurationImportSelector.class)

    META-INF/spring-autoconfigure-metadata.properties"

metaData里会定义onCondtionClass等限制

    META-INF/spring.factories

扫描工程所在path里这两个pattern的文件,得到

org.springframework.boot.autoconfigure.EnableAutoConfiguration 的类

                        String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());

processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);

      public String[] selectImports(AnnotationMetadata annotationMetadata) {

if (!isEnabled(annotationMetadata)) {

return NO_IMPORTS;

}

try {

AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader

.loadMetadata(this.beanClassLoader);

AnnotationAttributes attributes = getAttributes(annotationMetadata);

List<String> configurations = getCandidateConfigurations(annotationMetadata,

attributes);

configurations = removeDuplicates(configurations);

configurations = sort(configurations, autoConfigurationMetadata);

Set<String> exclusions = getExclusions(annotationMetadata, attributes);

checkExcludedClasses(configurations, exclusions);

configurations.removeAll(exclusions);

      //应用metaData里的OnConditionClass等,filter掉没有符合条件的Configuration 类

configurations = filter(configurations, autoConfigurationMetadata);

fireAutoConfigurationImportEvents(configurations, exclusions);

return configurations.toArray(new String[configurations.size()]);

}

catch (IOException ex) {

throw new IllegalStateException(ex);

}

}

6. registerBeanPostProcessors

如果BeanPostProcessor没有被实例化,则通过getBean进行实例化

7.  initMessageSource();, initApplicationEventMulticaster();

8. onRefresh

createEmbeddedServletContainer, 创建出  EmbeddedServletContainerFactory , 如Embeded Tomact

9.registerListeners

10 finishBeanFactoryInitialization(beanFactory);

对bean进行实例化

              beanFactory.preInstantiateSingletons();

总结:

对于一个SpringBoot Application应用, 首先会创建SpringApplicaiton这个实例,构造函数会生成一些Initializer和Listener。之后进入run方法。run方法主要会进行Envirmoment创建,准备。 AnnotationConfigEmbeddedWebApplicationContext的创建,初始化。context创建和初始化过程中会注册关键的一些BeanFactoryPostProcessor, BeanPostProcessors.

当环境和context都准备好后,进入refresh方法。refresh方法主要是过程是:准备BeanFactory (注册一下BeanPostProcessor,如ApplicationContextAwareProcessor)。之后调用BeanFactoryPostProcessor,这里一个关键ConfigurationClassPostProcessor会把工程下的Bean, 和工程下的EnableAutoConfiguration的Bean definition进行加载。之后会初始化BeanPostProcessor,最后进行实例化Bean。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 由于简书的markdown不支持目录结构,更好的阅读体验可以查看对应的个人blog: https://buaazh...
    yunkai_zhang阅读 727评论 0 0
  • org.springframework.beans: org.springframework.beans.fact...
    过河卒sc阅读 583评论 1 1
  • 文章作者:Tyan博客:noahsnail.com 3.5 Bean scopes When you create...
    SnailTyan阅读 1,874评论 0 1
  • 文/雨羡风 周末,想在家好好休息。鹏哥打电话,要我陪他去泉州。我问干嘛?他说去谈一笔生意。没啥事做,就答应了! 鹏...
    雨羡风阅读 262评论 0 1
  • 有些人相遇就是为了离去, 一场巷口完美的邂逅, 爱过吗,爱过, 爱她青春的年华, 爱她清脆的笑声, 爱她爽朗的性格...
    廿月雨阅读 177评论 0 5