Spring-Bean实例是如何依赖注入?

那什么是依赖注入呢?

所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。再完成IOC容器初始化之后,也就是所谓的Bean加载完成后,我们需要对这些Bean进行调用和获取,这个过程就叫依赖注入。

那什么时候会触发依赖注入呢?

通过getBean()方法获取Bean对象。

给Bean配置了懒加载,ApplicationContext启动完成后调用getBean()来实例化对象。

现在计算机性能已经足够,不是特殊要求下尽量别做懒加载,这样的话可以减少web运行时的调用时间开销。

好了,介绍完这些就开始我们的DI之旅。

1. BeanFactory

通过Spring获取Bean的最根本的接口。

getBean()方法有很多重载方法,上面只总结了一个。这个方法是DI的入口方法,接下来会从这个方法开始往下研究。

2. AbstractBeanFactory

从名字也能看出,这是BeanFactory的抽象实现类。

doGetBean()方法也是该类中的方法。

// 依赖注入 从这里开始发生

private <T> T doGetBean(

       final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

       throws BeansException {

   // 根据指定名字获取被管理Bean的名称

   // 如果是别名, 则转换为真正的bean名

   final String beanName = transformedBeanName(name);

   Object bean;

   // Eagerly check singleton cache for manually registered singletons.

   // 先从缓存中取单例 bean

   Object sharedInstance = getSingleton(beanName);

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

       if (logger.isDebugEnabled()) {

           // 如果有,则直接返回该bean

           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 的实例对象

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

   }

   else {

       // Fail if we're already creating this bean instance:

       // We're assumably within a circular reference.

       // 如果不是单例对象, 而且 缓存中有原型模式bean, 就抛异常

       if (isPrototypeCurrentlyInCreation(beanName)) {

           throw new BeanCurrentlyInCreationException(beanName);

       }

       // 检查 BeanDefinition 是否再当前的factory中, 如果不在则委托父类容器取查找

       // 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);

           }

       }

       if (!typeCheckOnly) {

           // 标记 bean 被创建

           markBeanAsCreated(beanName);

       }

       // 根据bean名称获取 父类的 beanDefinition, 合并继承公共属性

       final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

       checkMergedBeanDefinition(mbd, beanName, args);

       // Guarantee initialization of beans that the current bean depends on.

       // 获取当前bean 所有依赖Bean 的集合

       String[] dependsOn = mbd.getDependsOn();

       if (dependsOn != null) {

           for (String dependsOnBean : dependsOn) {

               // 递归调用, 获取当前Bean的依赖Bean

               getBean(dependsOnBean);

               // 把依赖Bean注册给当前的Bean

               registerDependentBean(dependsOnBean, beanName);

           }

       }

       // Create bean instance.

       // 创建bean 实例

       if (mbd.isSingleton()) {

           // 创建 bean 实例对象, 并且注册给所依赖的对象

           sharedInstance = getSingleton(beanName, new ObjectFactory() {

               public Object getObject() throws BeansException {

                   try {

                       // 创建一个指定bean 实例对象

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

       }

       else if (mbd.isPrototype()) {

           // It's a prototype -> create a new instance.

           Object prototypeInstance = null;

           try {

               beforePrototypeCreation(beanName);

               prototypeInstance = createBean(beanName, mbd, args);

           }

           finally {

               afterPrototypeCreation(beanName);

           }

           bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

       }

       // 如果创建的bean 不是单例也不是原型, 则根据声明周期选择实例化bean的方法

       // 如 request session 等不同范围的实例

       else {

           String scopeName = mbd.getScope();

           final Scope scope = this.scopes.get(scopeName);

           // 如果 scope 是空, 则抛异常

           if (scope == null) {

               throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");

           }

           // 否则

           try {

               // 获取一个指定了scope的bean实例

               Object scopedInstance = scope.get(beanName, new ObjectFactory() {

                   public Object getObject() throws BeansException {

                       beforePrototypeCreation(beanName);

                       try {

                           return createBean(beanName, mbd, args);

                       }

                       finally {

                           afterPrototypeCreation(beanName);

                       }

                   }

               });

               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

           }

           catch (IllegalStateException ex) {

               throw new BeanCreationException(beanName,

                       "Scope '" + scopeName + "' is not active for the current thread; " +

                       "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",

                       ex);

           }

       }

   }

   // Check if required type matches the type of the actual bean instance.

   // 检查是否需要类型检测

   if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {

       throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());

   }

   return (T) bean;

}

总结以下它都做了什么事情:

1、根据传来的bean的name(有可能是别名)来获取真正的bean名称:beanName。

2、根据beanName获取单例实例,如果有直接获取到bean实例并返回,DI完成。

3、如果根据beanName没有获得到单例实例:

3.1 判断是不是原型实例,如果是,则抛出创建失败异常,如果不是,下一步。

3.2 检查BeanDefinition是否在当前的容器中,如果不在那可能在父类容器中,所以委托父类容器查找,如果还没有,则再上一级容器...递归查找。

3.3 检查这个实例是否是为了类型检查而获取,而不是用来使用,如果是,标记这个bean已经被创建,如果不是,下一步。

3.4 根据beanName获取父类的BeanDefinition,并检查该对象类类型,比如不能是抽象类等。

3.5 根据beanName获取所有该bean依赖的Bean集合,如果该集合有值,则遍历DI(递归调用getBean())该bean集合里的bean,并把bean注册给当前的bean(维护了一个map来存放关系)。

3.6 如果3.4中获取的BeanDefinition是单例,则根据该单例对象和beanName和args创建一个实例对象;否则,判断BeanDefinition是否是原型,如果是则根据beanName,该对象,args创建一个实例;否则拿到3.4获取的BeanDefinition对象的生命周期Scope,然后根据scope来创建实例对象,参数(beanName,bd,args)。

3.7 检查是否需要类型检测

3.8 返回`3.1-3.7 `生成的实例。

然后我们再看看 createBean()方法的实现。

   protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)

           throws BeanCreationException;

3. AbstractAutowireCapableBeanFactory.java

// 创建bean 实例

@Override

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

       throws BeanCreationException {

   if (logger.isDebugEnabled()) {

       logger.debug("Creating instance of bean '" + beanName + "'");

   }

   // Make sure bean class is actually resolved at this point.

   // 解析和确定 bean 可以实例化

   resolveBeanClass(mbd, beanName);

   // Prepare method overrides.

   // 准备方法覆盖

   try {

       mbd.prepareMethodOverrides();

   }

   catch (BeanDefinitionValidationException ex) {

       throw new BeanDefinitionStoreException(mbd.getResourceDescription(),

               beanName, "Validation of method overrides failed", ex);

   }

   try {

       // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

       // 给 Bean处理器 一个机会, 返回一个目标bean实例

       Object bean = resolveBeforeInstantiation(beanName, mbd);

       if (bean != null) {

           return bean;

       }

   }

   catch (Throwable ex) {

       throw new BeanCreationException(mbd.getResourceDescription(), beanName,

               "BeanPostProcessor before instantiation of bean failed", ex);

   }

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

   if (logger.isDebugEnabled()) {

       logger.debug("Finished creating instance of bean '" + beanName + "'");

   }

   return beanInstance;

}

总结以下它都做了什么:

确定beanName和RootBeanDefinition可以被实例化。

执行方法覆盖

看BeanPostProcessors能否再解析之前获取到bean,如果能则直接返回,否则下一步。

调用doCreateBean()方法,获取bean实例.

doCreateBean()方法也是该类中的。

// 真正创建bean实例

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

   // Instantiat|e the bean.

   // 封装bean

   BeanWrapper instanceWrapper = null;

   if (mbd.isSingleton()) {

       // 如果是单例模式的bean,从容器中获取同名bean

       instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);

   }

   // 如果没有同名bean, 则创建bean实例

   if (instanceWrapper == null) {

       instanceWrapper = createBeanInstance(beanName, mbd, args);

   }

   // 如果有同名bean, 则获取到封装实例

   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);

   // 获取实例化对象类型

   Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

   // Allow post-processors to modify the merged bean definition.

   // 调用后置处理器

   synchronized (mbd.postProcessingLock) {

       if (!mbd.postProcessed) {

           applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

           mbd.postProcessed = true;

       }

   }

   // Eagerly cache singletons to be able to resolve circular references

   // even when triggered by lifecycle interfaces like BeanFactoryAware.

   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&

           isSingletonCurrentlyInCreation(beanName));

   if (earlySingletonExposure) {

       if (logger.isDebugEnabled()) {

           logger.debug("Eagerly caching bean '" + beanName +

                   "' to allow for resolving potential circular references");

       }

       addSingletonFactory(beanName, new ObjectFactory() {

           public Object getObject() throws BeansException {

               return getEarlyBeanReference(beanName, mbd, bean);

           }

       });

   }

   // Initialize the bean instance.

   // bean对象初始化, 依赖注入开始,exposedObject就是完成后的bean

   Object exposedObject = bean;

   try {

       // 将bean 实例封装, 并且 bean 定义中配置的属性值赋值给实例对象

       populateBean(beanName, mbd, instanceWrapper);

       // 初始化 bean对象

       exposedObject = initializeBean(beanName, exposedObject, mbd);

   }

   catch (Throwable ex) {

       if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {

           throw (BeanCreationException) ex;

       }

       else {

           throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);

       }

   }

   // 如果指定名称bean已经注册单例模式

   if (earlySingletonExposure) {

       Object earlySingletonReference = getSingleton(beanName, false);

       if (earlySingletonReference != null) {

           if (exposedObject == bean) {

               // 如果两个对象相等, bean初始化完成

               exposedObject = earlySingletonReference;

           }

           // 如果不相等, 则找出当前bean的依赖bean

           else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {

               String[] dependentBeans = getDependentBeans(beanName);

               Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);

               for (String dependentBean : dependentBeans) {

                   // 检查依赖bean (是否继承接口,是否是父子关系。。)

                   if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {

                       actualDependentBeans.add(dependentBean);

                   }

               }

               if (!actualDependentBeans.isEmpty()) {

                   throw new BeanCurrentlyInCreationException(beanName,

                           "Bean with name '" + beanName + "' has been injected into other beans [" +

                           StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +

                           "] in its raw version as part of a circular reference, but has eventually been " +

                           "wrapped. This means that said other beans do not use the final version of the " +

                           "bean. This is often the result of over-eager type matching - consider using " +

                           "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");

               }

           }

       }

   }

   // Register bean as disposable.

   // 注册完成依赖注入的bean

   try {

       registerDisposableBeanIfNecessary(beanName, bean, mbd);

   }

   catch (BeanDefinitionValidationException ex) {

       throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);

   }

   return exposedObject;

}

同样,总结以下它干的事情:

根据beanName获取beanWrapper对象。如果beanWrapper对象是空,则调用createBeanInstance()方法创建bean实例。否则,下一步

通过beanWrapper对象获取bean实例和class类型。

允许postProcessors调整组合BeanDefinition。

如果RootBeanDefinition是单例并且允许循环引用并且beanName正在进行单例创建,将beanName添加到单例工厂。

调用populateBean()方法给bean的属性值赋值,然后初始化bean对象并返回创建的bean实例,如果抛异常,则下一步。

如果该beanName对象已经注册单例模式,则从单例中获取,并判断获取到的bean实例(B)与BeanWrapper中的bean实例(A)是同一个实例,如果是,则返回A或者B,如果不是,则递归找出它的依赖bean。

返回1-6产生的bean实例。

我们首次获取bean实例的时候,bean工厂是肯定没有的,所以我们首次获取到的BeanWrapper应该是空对象,但是它调用了createBeanInstance()方法后,可以看到spring是很确定它能拿到对象,那么我们看看这个方法的实现。它仍然是这个类中的方法。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {

   // Make sure bean class is actually resolved at this point.

   // 确保bean可实例化(不能是抽象类等)

   Class beanClass = resolveBeanClass(mbd, beanName);

   // 如果这个bean 不是public 修饰符或者不被允许公共访问, 抛出异常

   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {

       throw new BeanCreationException(mbd.getResourceDescription(), beanName,

               "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());

   }

   if (mbd.getFactoryMethodName() != null)  {

       // 通过工厂方法实例化

       return instantiateUsingFactoryMethod(beanName, mbd, args);

   }

   // Shortcut when re-creating the same bean...

   // 是否有构造器

   if (mbd.resolvedConstructorOrFactoryMethod != null && args == null) {

       if (mbd.constructorArgumentsResolved) {

           return autowireConstructor(beanName, mbd, null, null);

       }

       else {

           return instantiateBean(beanName, mbd);

       }

   }

   // Need to determine the constructor...

   // 需要确认构造器

   Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

   if (ctors != null ||

           mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||

           mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {

       // 自动装配,调用匹配的构造方法进行实例化

       return autowireConstructor(beanName, mbd, ctors, args);

   }

   // No special handling: simply use no-arg constructor.

   // 使用默认无参构造

   return instantiateBean(beanName, mbd);

}

这个类用来创建Bean实例,然后返回BeanWrapper对象。注释写的很详细了。其中有个instantiateBean()方法,当没有参数和构造方法的时候,就会调用该方法来实例化bean。

// 使用默认无参构造方法实例化bean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {

   try {

       Object beanInstance;

       final BeanFactory parent = this;

       // 获取JDK安全管理

       if (System.getSecurityManager() != null) {

           // 根据实例化策略实例化对象

           beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {

               public Object run() {

                   return getInstantiationStrategy().instantiate(mbd, beanName, parent);

               }

           }, getAccessControlContext());

       }

       else {

           beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

       }

       // 对实例化对象进行封装

       BeanWrapper bw = new BeanWrapperImpl(beanInstance);

       initBeanWrapper(bw);

       return bw;

   }

   catch (Throwable ex) {

       throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);

   }

}

这个方法是使用默认无参构造方法实例化bean的,它的核心代码是getInstantiationStrategy().instantiate(mbd,beanName,parent);,因为它,我们可以得到一个bean实例对象,然后封装成BeanWrapper并返回。

4. SimpleInstantiationStrategy.java

用于BeanFactory的简单对象实例化策略。不支持方法注入,尽管它提供了子类的hook来覆盖以添加方法注入支持,例如通过重写方法。

// 使用初始化策略 实例化bean

public Object instantiate(

       RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

   // Don't override the class with CGLIB if no overrides.

   // 如果beanDefinition 中没有方法覆盖, 就用jdk,否则用cglib

   if (beanDefinition.getMethodOverrides().isEmpty()) {

       // 获取对象的构造方法和工厂方法

       Constructor constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod;

       if (constructorToUse == null) {

           // 如果 没有构造方法和工厂方法, 使用JDK反射, 判断实例化的bean是不是接口

           final Class clazz = beanDefinition.getBeanClass();

           if (clazz.isInterface()) {

               throw new BeanInstantiationException(clazz, "Specified class is an interface");

           }

           try {

               if (System.getSecurityManager() != null) {

                   // 使用反射获取bean构造方法

                   constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {

                       public Constructor run() throws Exception {

                           return clazz.getDeclaredConstructor((Class[]) null);

                       }

                   });

               } else {

                   constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);

               }

               beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;

           }

           catch (Exception ex) {

               throw new BeanInstantiationException(clazz, "No default constructor found", ex);

           }

       }

       // 使用beanUtils实例化   构造方法.newInstance(arg) 来实例化

       return BeanUtils.instantiateClass(constructorToUse);

   }

   else {

       //如果 有覆盖或者重写, 则用CGLIB来实例化对象

       // Must generate CGLIB subclass.

       return instantiateWithMethodInjection(beanDefinition, beanName, owner);

   }

}

总结它的步骤:

如果BeanDefinition的覆盖方法不为空,则交给CGLIB来实例化对象,否则获取构造方法和工厂方法,下一步。

如果没有构造方法和工厂方法,则使用JDK反射,判断实例化的bean是不是接口,如果是,抛出异常,如果不是,则使用反射来获取bean的构造方法,最后,用构造器.newInstance()的方法(BeanUtils.instantiateClass()方法底层实现)来实例化并返回。

那cglib是如何实例化呢,我们来看下instantiateWithMethodInjection(beanDefinition,beanName,owner);方法源码:

@Override

protected Object instantiateWithMethodInjection(

       RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

   // Must generate CGLIB subclass.

   return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null);

}

然后再跟进CglibSubclassCreator(beanDefinition,owner).instantiate(null,null);方法:

// 使用cglib 来进行bean实例化

public Object instantiate(Constructor ctor, Object[] args) {

   // cglib

   Enhancer enhancer = new Enhancer();

   // bean本身作为基类

   enhancer.setSuperclass(this.beanDefinition.getBeanClass());

   enhancer.setCallbackFilter(new CallbackFilterImpl());

   enhancer.setCallbacks(new Callback[] {

           NoOp.INSTANCE,

           new LookupOverrideMethodInterceptor(),

           new ReplaceOverrideMethodInterceptor()

   });

   // 生成实例对象

   return (ctor == null) ?

           enhancer.create() :

           enhancer.create(ctor.getParameterTypes(), args);

}

从上面代码可以看到,这就是CGLIB动态代理中创建代理的过程代码。

好了,到了这里,Spring就完成了bean实例的创建,但是此时就能拿着这个实例去使用吗,显然是不可以,因为属性还没有被赋入,下一章再继续介绍如何将属性依赖关系注入到Bean实例对象。

如果您Java学习的过程中遇到难题,欢迎关注微信公众号【潭州筑梦Java】,大家一起交流讨论解决!

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

推荐阅读更多精彩内容