SpringIOC和AOP原理 設(shè)計(jì)模式

SpringIOC的特點(diǎn)

在接觸Spring的過程中镰惦,聽到最多的無非兩個(gè)名詞靠欢,一個(gè)是控制反轉(zhuǎn)一個(gè)是依賴注入舵匾。實(shí)際這是一個(gè)意思飒炎,控制反轉(zhuǎn)代表原來由程序本身去控制對象之間的依賴關(guān)系的這種格局被反轉(zhuǎn)了诡曙,通過第三方容器(IOC)去完成控制這些對象的依賴的關(guān)系并對它們進(jìn)行集中管理臀叙。

依賴注入:獲得依賴對象的過程由自身管理變?yōu)榱擞蒊OC容器主動(dòng)注入,就是由IOC容器在運(yùn)行期間价卤,動(dòng)態(tài)地將某種依賴關(guān)系注入到對象之中劝萤。

SpringAOP的特點(diǎn)
AOP最多聽到的就是面向切面編程,那對于這個(gè)名詞慎璧,我第一次聽到的時(shí)候也是不能理解的。

下面用一個(gè)圖和語言來進(jìn)行描述:

切面

在一個(gè)項(xiàng)目中和我們業(yè)務(wù)邏輯和通用的邏輯區(qū)分開來厌处,比如我們的一個(gè)系統(tǒng)需要記錄日志岁疼,記錄日志這個(gè)事情是通用的阔涉,不管你做什么系統(tǒng)一般都會(huì)涉及瑰排。那么這一塊就通過AOP來統(tǒng)一集中實(shí)現(xiàn),統(tǒng)一管理暖侨。

生活中的一個(gè)例子椭住,你去吃飯之前肯定要洗手函荣,飯后肯定要擦嘴扳肛。那么挖息,不管你吃什么飯?jiān)谀膫€(gè)地方吃。這些通用的過程你都要執(zhí)行绪抛。那么集中抽象出來這些方法幢码,也就形成了AOP症副。

SpringIOC容器加載Bean的過程

1.第一步 IOC容器


初始化

把xml文件位置信息保存贞铣,然后調(diào)用refresh方法去重新初始化一個(gè)新的IOC容器辕坝,Refresh方法中使用obtainFreshBeanFactory去獲取,后面的代碼是一些BeanFactory創(chuàng)建后的后處理過程


1.1

obtainFreshBeanFactory方法里面琳袄,我們看到第一行調(diào)用refreshBeanFactory的方法去創(chuàng)建窖逗。


1.2

在方法中去loadBeanDefintions(),使用XMLReader去解析我們的xml配置文件


1.3

后面省略一些源碼的步驟用含,主要做的就是對xml文件進(jìn)行解析成我們要的BeanDefinitions啄骇,處理每個(gè)Bean元素以及元素中的屬性值缸夹。最后把beanDefinition注冊進(jìn)我們的BeanFactory中虽惭,

1.4

2.注入依賴

2.1
2.2

AOP的兩種實(shí)現(xiàn)方式 以及小例子

主要是兩種芽唇,一種是JDK動(dòng)態(tài)代理匆笤,一種是Cglib代理炮捧。

兩者的區(qū)別:
1.JDK動(dòng)態(tài)代理只能代理實(shí)現(xiàn)了接口的類咆课,動(dòng)態(tài)代理類的字節(jié)碼在程序運(yùn)行時(shí)由Java反射機(jī)制動(dòng)態(tài)生成傀蚌。
2.Cglib是可以代理沒有實(shí)現(xiàn)接口的類,cglib是針對類來實(shí)現(xiàn)代理的撩幽,他的原理是對指定的目標(biāo)類生成一個(gè)子類窜醉,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng)榨惰,所以不能對final修飾的類進(jìn)行代理静汤。底層采用ASM實(shí)現(xiàn)虫给。

Cglib的例子:

package com.Model.CGlibProxy;

public interface AddBook {
    public void addbook();
}

package com.Model.CGlibProxy;

public class AddBookImp implements AddBook {

    @Override
    public void addbook() {
        // TODO Auto-generated method stub
        System.out.println("添加書籍....");
    }

}

package com.Model.CGlibProxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

    private Object target;

    public Object getInstance(Object target) {
        this.target = target;

        Enhancer enhancer = new Enhancer();
        // 設(shè)置自己的父類
        enhancer.setSuperclass(target.getClass());
        // 關(guān)聯(lián)的要使用哪個(gè)對象的回調(diào)函數(shù) 這里指向自己這個(gè)對象的回調(diào) 那么就是下面這個(gè)方面了
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
        // TODO Auto-generated method stub

        System.out.println("事務(wù)開始...");
        // 調(diào)用父類函數(shù)
        arg3.invokeSuper(arg0, arg2);

        System.out.println("事務(wù)結(jié)束....");

        return null;
    }

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        AddBookImp oBookImp = (AddBookImp) cglibProxy.getInstance(new AddBookImp());
        oBookImp.addbook();
    }

}

JDK動(dòng)態(tài)代理:

//操作定義
public interface SubjectOperations {
    // 打印操作
    public void print();

    // 打印輸入字符串操作
    public void printfStr(String string);
}

public class RealSubject implements SubjectOperations {

    @Override
    public void print() {
        System.out.println("我實(shí)現(xiàn)了接口 完成這個(gè)打印操作");

    }

    @Override
    public void printfStr(String string) {
        // TODO Auto-generated method stub
        System.out.println("打印輸入的內(nèi)容:  " + string);
    }

}

public class LogHandler implements InvocationHandler {

    private Object ImpClass;
    private Object lObject;

    public LogHandler(Object realObject) {
        this.ImpClass = realObject;
    }

    public Object bind(Object impclass, Object iObject) {
        this.ImpClass = impclass;
        this.lObject = iObject;
        return Proxy.newProxyInstance(impclass.getClass().getClassLoader(), impclass.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("在目標(biāo)方法調(diào)用前執(zhí)行.....");
        method.invoke(ImpClass, args);
        System.out.println("在目標(biāo)方法調(diào)用后執(zhí)行....");
        return null;
    }

    public static void main(String[] args) {

    }
}

class Client {
    public static void main(String[] args) {
        RealSubject subject = new RealSubject();
        LogHandler handler = new LogHandler(subject);

        // 轉(zhuǎn)化成接口 只能代理實(shí)現(xiàn)了接口的類
        SubjectOperations pSubject1 = (SubjectOperations) handler.bind(subject, new LoggerImp());
        System.out.println(pSubject1.getClass().getName());

        pSubject1.print();
        pSubject1.printfStr("YYYYY");
    }
}

面試官說讓你講講IOC和AOP時(shí),他們想了解什么瓷式?我應(yīng)該怎么回答

這個(gè)問題我也很頭痛贸典,這里我找到一個(gè)模版瓤漏,我打算以后就這樣回答。大家也可以參考一下:

知乎

我的回答:
Spring是一套為了解決企業(yè)應(yīng)用開發(fā)的復(fù)雜性而創(chuàng)建的框架,特點(diǎn)是分層的架構(gòu)榨呆,允許用戶在不同層面使用不同的組件進(jìn)行組合庸队。同時(shí)通過IOC容器來降低耦合彻消,簡化開發(fā)宾尚。利用AOP來進(jìn)行切面編程統(tǒng)一管理通用模塊煌贴。

我在工作中用到過Spring的IOC容器和AOP面向切面編程,在項(xiàng)目中使用IOC容器幫我很好的理清各個(gè)業(yè)務(wù)對象的關(guān)系怠肋,同時(shí)方便不同組件的更替笙各。在做接口權(quán)限驗(yàn)證時(shí)杈抢,使用AOP切面編程幫助我能很快的對需要進(jìn)行驗(yàn)證的接口完成驗(yàn)證功能的實(shí)現(xiàn)春感。并且統(tǒng)一進(jìn)行管理,提高開發(fā)效率嫩实。

SpringMVC的大致實(shí)現(xiàn)過程

SpringMVC請求過程

1.用戶發(fā)起一個(gè)request請求宰缤,如果有多個(gè)DispatcherServlet,則通過Servletmapping去指定執(zhí)行的DispatcherServlet朦乏。
2.DispatcherServlet把根據(jù)URL請求呻疹,去HandlerMapping中查找注冊了的URL映射刽锤,并返回相應(yīng)的Handler(一個(gè)Controller并思,多個(gè)攔截器)宋彼,給DispatcherServlet颅筋。
3.DispatcherServlet傳遞Handler給HandlerAdapter去執(zhí)行议泵,返回一個(gè)ModelAndView先口。
4.DispatcherServlet把ModelAndView傳遞給視圖解析器去解析碉京,返回一個(gè)視圖view谐宙。
5.組裝上Model數(shù)據(jù)后變成Response請求返回給客戶端凡蜻。

SpringIOC和AOP中用到的設(shè)計(jì)模式

簡單工廠

在Spring中經(jīng)常利用BeanFactory的getBean方法去獲取Bean就是一個(gè)簡單工廠的設(shè)計(jì)模式的實(shí)現(xiàn),通過Bean的ID去獲取這個(gè)對象的實(shí)例兑巾。Bean的ID一般配置在XML文件中

工廠方法

在工廠方法模式中蒋歌, Spring不會(huì)直接利用反射機(jī)制創(chuàng)建bean對象堂油, 而是會(huì)利用反射機(jī)制先找到Factory類府框,然后利用Factory再去生成bean對象寓免。

而Factory Mothod方式也分兩種袜香, 分別是靜態(tài)工廠方法 和 實(shí)例工廠方法蜈首。

靜態(tài)工廠方法

定義一個(gè)類

public class Car {
    private int id;
    private String name;
    private int price;

//省略構(gòu)造函數(shù) getter和setter函數(shù)
}

定義一個(gè)靜態(tài)工廠類

public class CarStaticFactory {
    private static Map<Integer, Car> map = new HashMap<Integer,Car>();

    static{
        map.put(1, new Car(1,"Honda",300000));
        map.put(2, new Car(2,"Audi",440000));
        map.put(3, new Car(3,"BMW",540000));
    }

    public static Car getCar(int id){
        return map.get(id);
    }
}

XML中的配置文件欢策,可以看到我們指定的class不再是具體的Bean踩寇,而是生產(chǎn)Bean的工廠俺孙,然后通過工廠方法去創(chuàng)建,有一點(diǎn)不好的地方就是map的初始化在程序中進(jìn)行荣茫,耦合度相對高

  <!-- 
        Static Factory method:
        class: the class of Factory
        factory-method: method of get Bean Object
        constructor-arg: parameters of factory-method
     -->
    <bean id="bmwCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
        <constructor-arg value="3"></constructor-arg>           
    </bean>

    <bean id="audiCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
        <constructor-arg value="2"></constructor-arg>           
    </bean>

實(shí)例工廠

我們創(chuàng)建一個(gè)工廠,這次獲取car的方法不是靜態(tài)的了咧欣。

public class CarInstanceFactory {
    private Map<Integer, Car> map = new HashMap<Integer,Car>();

    public void setMap(Map<Integer, Car> map) {
        this.map = map;
    }

    public CarInstanceFactory(){
    }

    public Car getCar(int id){
        return map.get(id);
    }
}

XML配置文件该押,把工廠的初始化在文件中配置完成蚕礼。不用在代碼中編寫奠蹬。

<!-- Instance Factory Method:
         1.must create a bean for the Instance Factroy First
     -->
     <bean id="carFactory" class="com.home.factoryMethod.CarInstanceFactory">
        <property name="map">
            <map>
                <entry key="4">
                        <bean class="com.home.factoryMethod.Car">
                            <property name="id" value="4"></property>   
                            <property name="name" value="Honda"></property> 
                            <property name="price" value="300000"></property>   
                        </bean>
                </entry>    

                <entry key="6">
                        <bean class="com.home.factoryMethod.Car">
                            <property name="id" value="6"></property>   
                            <property name="name" value="ford"></property>  
                            <property name="price" value="500000"></property>   
                        </bean>
                </entry>
            </map>  
        </property>
     </bean>

     <!-- 2.use Factory bean to get bean objectr 
        factory-bean : the bean define above
        factory-method: method of get Bean Object
        constructor-arg: parameters of factory-method
     -->
     <bean id="car4" factory-bean="carFactory" factory-method="getCar">
        <constructor-arg value="4"></constructor-arg>           
     </bean>

     <bean id="car6" factory-bean="carFactory" factory-method="getCar">
        <constructor-arg value="6"></constructor-arg>           
     </bean

單例模式

保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)狸演。
spring中的單例模式完成了后半句話宵距,即提供了全局的訪問點(diǎn)BeanFactory吨拗。但沒有從構(gòu)造器級別去控制單例劝篷,這是因?yàn)閟pring管理的是是任意的java對象娇妓。

下面問答中會(huì)專門說一下Spring中的單例模式

核心提示點(diǎn):Spring下默認(rèn)的bean均為singleton哈恰,可以通過singleton=“true|false” 或者 scope=“蕊蝗?”來指定

代理模式

為其他對象提供一種代理以控制對這個(gè)對象的訪問蓬戚。 從結(jié)構(gòu)上來看和Decorator模式類似子漩,但Proxy是控制幢泼,更像是一種對功能的限制缕棵,而Decorator是增加職責(zé)。
spring的Proxy模式在aop中有體現(xiàn)篙程,比如JdkDynamicAopProxy和Cglib2AopProxy虱饿。

觀察者模式

定義對象間的一種一對多的依賴關(guān)系氮发,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí)宾娜,所有依賴于它的對象都得到通知并被自動(dòng)更新扇售。
spring中Observer模式常用的地方是listener的實(shí)現(xiàn)浓镜。如ApplicationListener困乒。ServletContextListener

servlet和Filter初始化前和銷毀后娜搂,都會(huì)給實(shí)現(xiàn)了servletContextListener接口的監(jiān)聽器發(fā)出相應(yīng)的通知百宇。

模板方法

定義一個(gè)操作中的算法的骨架携御,而將一些步驟延遲到子類中啄刹。Template Method使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟誓军。
Template Method模式一般是需要繼承的昵时。這里想要探討另一種對Template Method的理解。spring中的JdbcTemplate,在用這個(gè)類時(shí)并不想去繼承這個(gè)類征绸,因?yàn)檫@個(gè)類的方法太多管怠,但是我們還是想用到JdbcTemplate已有的穩(wěn)定的渤弛、公用的數(shù)據(jù)庫連接她肯,那么我們怎么辦呢晴氨?我們可以把變化的東西抽出來作為一個(gè)參數(shù)傳入JdbcTemplate的方法中籽前。但是變化的東西是一段代碼枝哄,而且這段代碼會(huì)用到JdbcTemplate中的變量挠锥。怎么辦瘪贱?那我們就用回調(diào)對象吧菜秦。在這個(gè)回調(diào)對象中定義一個(gè)操縱JdbcTemplate中變量的方法,我們?nèi)?shí)現(xiàn)這個(gè)方法眨攘,就把變化的東西集中到這里了。然后我們再傳入這個(gè)回調(diào)對象到JdbcTemplate该肴,從而完成了調(diào)用。這可能是Template Method不需要繼承的另一種實(shí)現(xiàn)方式吧涎嚼。

不用繼承的模版方法
我們把想要的connection連接賦值到回調(diào)對象中
獲取從JDBCTemplate中傳入的穩(wěn)定的Connection對象,進(jìn)行自己定義的操作
繼承的模版方法立哑,比如常見

我們定義一個(gè)算法的執(zhí)行過程刁憋,里面會(huì)調(diào)用4個(gè)小步驟木蹬,具體的小步驟的實(shí)現(xiàn)我們交過實(shí)現(xiàn)的子類去完成至耻。然后用戶調(diào)用整個(gè)process方法就能實(shí)現(xiàn)功能。

public abstract class EntityProcessor {
 
    public final void processEntity() {
        getEntityData();
        createEntity();
        validateEntity();
        persistEntity();
    }
 
    protected abstract void getEntityData();
    protected abstract void createEntity();
    protected abstract void validateEntity();
    protected abstract void persistEntity();
 
}

IOC 的單例模式是怎么實(shí)現(xiàn)的

IOC的單例模式不是使用的懶漢式或者餓漢式镊叁,使用的是

單例注冊表尘颓,通過把Bean的名稱和對象組成的key-value注冊進(jìn)HashMap中。每次需要獲取相應(yīng)的類時(shí)晦譬,根據(jù)名稱去獲取疤苹,如果沒有這個(gè)bean就去讀取Bean的定義敛腌。估計(jì)type是需要單例還是多例卧土,如果是單例注冊進(jìn)入表并返回,如是多例不注冊像樊,創(chuàng)建一個(gè)Bean并返回尤莺。

public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{    
   /**  
    * 充當(dāng)了Bean實(shí)例的緩存,實(shí)現(xiàn)方式和單例注冊表相同  
    */    
   private final Map singletonCache=new HashMap();    
   public Object getBean(String name)throws BeansException{    
       return getBean(name,null,null);    
   }    
...    
   public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{    
      //對傳入的Bean name稍做處理生棍,防止傳入的Bean name名有非法字符(或則做轉(zhuǎn)碼)    
      String beanName=transformedBeanName(name);    
      Object bean=null;    
      //手工檢測單例注冊表    
      Object sharedInstance=null;    
      //使用了代碼鎖定同步塊颤霎,原理和同步方法相似,但是這種寫法效率更高    
      synchronized(this.singletonCache){    
         sharedInstance=this.singletonCache.get(beanName);    
       }    
      if(sharedInstance!=null){    
         ...    
         //返回合適的緩存Bean實(shí)例    
         bean=getObjectForSharedInstance(name,sharedInstance);    
      }else{    
        ...    
        //取得Bean的定義    
        RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);    
         ...    
        //根據(jù)Bean定義判斷,此判斷依據(jù)通常來自于組件配置文件的單例屬性開關(guān)    
        //<bean id="date" class="java.util.Date" scope="singleton"/>    
        //如果是單例友酱,做如下處理    
        if(mergedBeanDefinition.isSingleton()){    
           synchronized(this.singletonCache){    
            //再次檢測單例注冊表    
             sharedInstance=this.singletonCache.get(beanName);    
             if(sharedInstance==null){    
                ...    
               try {    
                  //真正創(chuàng)建Bean實(shí)例    
                  sharedInstance=createBean(beanName,mergedBeanDefinition,args);    
                  //向單例注冊表注冊Bean實(shí)例    
                   addSingleton(beanName,sharedInstance);    
               }catch (Exception ex) {    
                  ...    
               }finally{    
                  ...    
              }    
             }    
           }    
          bean=getObjectForSharedInstance(name,sharedInstance);    
        }    
       //如果是非單例晴音,即prototpye,每次都要新創(chuàng)建一個(gè)Bean實(shí)例    
       //<bean id="date" class="java.util.Date" scope="prototype"/>    
       else{    
          bean=createBean(beanName,mergedBeanDefinition,args);    
       }    
}    
...    
   return bean;    
}    
} 

如何保證IOC中有狀態(tài)Bean的線程安全

有狀態(tài)Bean就是一些Bean實(shí)例中含有一些非線程安全的成員變量缔杉,那么當(dāng)多個(gè)線程去同時(shí)操作這個(gè)Bean時(shí)锤躁,就有可能導(dǎo)致對這些變量的操作出現(xiàn)問題。

使用ThreadLocal類可以做到或详,ThreadLocal會(huì)為變量在每個(gè)線程中創(chuàng)建本地變量副本系羞,那么每個(gè)線程可以訪問自己內(nèi)部的副本變量。大家互不干擾鸭叙,以此達(dá)到線程安全的目的觉啊。

最常見的數(shù)據(jù)庫連接管理類:

class ConnectionManager {
     
    private static Connection connect = null;
     
    public static Connection openConnection() {
        if(connect == null){
            connect = DriverManager.getConnection();
        }
        return connect;
    }
     
    public static void closeConnection() {
        if(connect!=null)
            connect.close();
    }
}

第一拣宏,這里面的2個(gè)方法都沒有進(jìn)行同步沈贝,很可能在openConnection方法中會(huì)多次創(chuàng)建connect;第二勋乾,由于connect是共享變量宋下,那么必然在調(diào)用connect的地方需要使用到同步來保障線程安全,因?yàn)楹芸赡芤粋€(gè)線程在使用connect進(jìn)行數(shù)據(jù)庫操作辑莫,而另外一個(gè)線程調(diào)用closeConnection關(guān)閉鏈接学歧。

使用ThreadLocal后:

當(dāng)多個(gè)線程去取session的時(shí)候,都會(huì)去拿自己線程的本地變量副本各吨,沒有就創(chuàng)建一個(gè)注冊進(jìn)去并返回枝笨。

private static final ThreadLocal threadSession = new ThreadLocal();
 
public static Session getSession() throws InfrastructureException {
    Session s = (Session) threadSession.get();
    try {
        if (s == null) {
            s = getSessionFactory().openSession();
            threadSession.set(s);
        }
    } catch (HibernateException ex) {
        throw new InfrastructureException(ex);
    }
    return s;
}

舉例說明IOC如何使用,AOP如何使用

IOC的使用:
首先定義你需要的Bean的類以及成員變量揭蜒,然后將這些類全部注冊到Spring的ApplicationContext.xml文件中横浑,然后在xml文件進(jìn)進(jìn)行依賴配置。之后只需要在程序中創(chuàng)建一個(gè)BeanFactory屉更,加載XML文件徙融,getBean就能獲得我們要的實(shí)例了

AOP使用Aspectj:
定義一個(gè)Advice類,里面進(jìn)行一個(gè)或多個(gè)pointcut的定義瑰谜,以及在哪個(gè)pointcut下使用那些方法欺冀,

定義的pointcut方法本身只是用來標(biāo)記的,用于指定在哪里進(jìn)行一個(gè)切入萨脑,比如這里我使用的是within代表切入NeedLogService類中的所有方法


定義一個(gè)pointcut

有執(zhí)行前的隐轩,有執(zhí)行后的,有異常時(shí)的


定義切面方法

當(dāng)我們調(diào)用這個(gè)類的方法時(shí)渤早,就會(huì)發(fā)現(xiàn)被增強(qiáng)了


被代理類定義
測試調(diào)用
輸出

參考文章:
Spring IOC核心源碼學(xué)習(xí)
使用 IoC 反轉(zhuǎn)控制的三種設(shè)計(jì)模式
Spring的單例模式底層實(shí)現(xiàn)
Spring中Singleton模式的線程安全
【SSH進(jìn)階之路】Spring的AOP逐層深入——采用注解完成AOP(七)
深入解析spring中用到的九種設(shè)計(jì)模式
Spring 通過工廠方法(Factory Method)來配置bean

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末龙助,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌提鸟,老刑警劉巖军援,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異称勋,居然都是意外死亡胸哥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門赡鲜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來空厌,“玉大人,你說我怎么就攤上這事银酬〕案” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵揩瞪,是天一觀的道長赋朦。 經(jīng)常有香客問我,道長李破,這世上最難降的妖魔是什么宠哄? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮嗤攻,結(jié)果婚禮上毛嫉,老公的妹妹穿的比我還像新娘。我一直安慰自己妇菱,他們只是感情好承粤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著闯团,像睡著了一般辛臊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上偷俭,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天浪讳,我揣著相機(jī)與錄音,去河邊找鬼涌萤。 笑死淹遵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的负溪。 我是一名探鬼主播透揣,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼川抡!你這毒婦竟也來了辐真?” 一聲冷哼從身側(cè)響起须尚,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侍咱,沒想到半個(gè)月后耐床,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡楔脯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年撩轰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昧廷。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡堪嫂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出木柬,到底是詐尸還是另有隱情皆串,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布眉枕,位于F島的核電站恶复,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏齐遵。R本人自食惡果不足惜寂玲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一塔插、第九天 我趴在偏房一處隱蔽的房頂上張望梗摇。 院中可真熱鬧,春花似錦想许、人聲如沸伶授。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糜烹。三九已至,卻和暖如春漱凝,著一層夾襖步出監(jiān)牢的瞬間疮蹦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工茸炒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留愕乎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓壁公,卻偏偏與公主長得像感论,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子紊册,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理比肄,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,626評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法芳绩,類相關(guān)的語法掀亥,內(nèi)部類的語法,繼承相關(guān)的語法妥色,異常的語法铺浇,線程的語...
    子非魚_t_閱讀 31,596評論 18 399
  • 什么是Spring Spring是一個(gè)開源的Java EE開發(fā)框架。Spring框架的核心功能可以應(yīng)用在任何Jav...
    jemmm閱讀 16,445評論 1 133
  • 道左紅似火垛膝, 紅似六月花鳍侣; 路右綠婆娑 , 綠如朦朧紗吼拥; 曲徑通幽處倚聚, 宛若一幅畫; 小溪哼著歌凿可, 前方是我家……
    天馬行空我也閱讀 212評論 6 4
  • 婚禮邀請函還在發(fā)紙質(zhì)的嗎惑折?還在發(fā)那種毫無創(chuàng)意的卡片嗎?土枯跑! 讓來畫君教你如何制作創(chuàng)意滿滿的婚禮邀請函視頻惨驶, 讓你的...
    愛畫畫的臭皮匠閱讀 1,638評論 2 0