Spring4.3.8學習[三]

如果轉(zhuǎn)載文章請注明出處, 謝謝 !
本系列文章是學習完 Spring4.3.8 后的詳細整理, 如果有錯誤請向我指明, 我會及時更正~??

Spring4.3.8

Spring4.3.8學習[一]
Spring4.3.8學習[二]

4. 面向切面編程

這里有一張網(wǎng)上看到的圖我覺得也蠻適合理解的, 可以看完下面的代理之后返回來仔細看看這張圖能夠更容易理解:


AOP

4.1 代理模式

我們在 Hibernate 中處理增刪改功能都要添加事務, 代碼如下:

public class UserDaoImpl implements UserDao {
    @Override
    public void insertUser() {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        System.out.println("插入用戶");

        transaction.commit();
        session.close();
    }

    @Override
    public void delete(Integer uid) {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        System.out.println("刪除用戶");

        transaction.commit();
        session.close();
    }
}

事務和邏輯的處理混雜在一起, 如果再增添方法還需要繼續(xù)重復有關(guān)事務的重復代碼.
或者需求發(fā)生了變化爬凑,要求項目中所有的類在執(zhí)行方法時輸出執(zhí)行耗時萎馅。最直接的辦法是修改源代碼
缺點:
1讹开、工作量特別大痊乾,如果項目中有多個類,多個方法,則要修改多次。
2您旁、違背了一些設(shè)計原則:
開閉原則(OCP)[對擴展開放,對修改關(guān)閉轴捎,而為了增加功能把每個方法都修改了鹤盒,也不便于維護。]
單一職責(SRP)[每個方法除了要完成自己本身的功能侦副,還要計算耗時侦锯、延時;每一個方法引起它變化的原因就有多種跃洛。]

4.1.1 靜態(tài)代理

1率触、定義UserDao接口, 抽象主題

public interface UserDao{
    void insertUser();
    void delete(Integer uid);
}

2、實現(xiàn)UserDao接口, 被代理的目標對象, 真實主題

public class UserDaoImpl implements UserDao {
    @Override
    public void insertUser() {
        System.out.println("插入用戶");

    }
    @Override
    public void delete(Integer uid) {
        System.out.println("刪除用戶");

    }
}

3汇竭、代理類, 靜態(tài)代理類

public class UserDaoProxy implements UserDao{
      //被代理的對象
    private UserDao userDao;
    private Transaction transaction;

    public UserDaoProxy(UserDao userDao, Transaction transaction) {
        this.userDao = userDao;
        this.transaction = transaction;
    }

    @Override
    public void insertUser() {
        transaction.beginTransaction();
        userDao.insertUser();
        transaction.commitTransaction();
    }

    @Override
    public void delete(Integer uid) {
        transaction.beginTransaction();
        userDao.insertUser();
        transaction.commitTransaction();
    }
}

4葱蝗、測試

public class ProxyTest {
    @Test
    public void testProxy(){
        UserDao dao = new UserDaoImpl();
        Transaction transaction = new Transaction();
        UserDaoProxy proxy = new UserDaoProxy(dao, transaction);
        proxy.insertUser();
    }
}

通過靜態(tài)代理可以解決這些設(shè)計原則問題, 但是不能解決:
如果項目中有多個類,則需要編寫多個代理類细燎,工作量大两曼,不好修改,不好維護玻驻,不能應對變化.
如果要解決上面的問題悼凑,可以使用動態(tài)代理

4.1.2 JDK動態(tài)代理

JDK的動態(tài)代理主要涉及 java.lang.reflect 包中的兩個類:Proxy和InvocationHandler偿枕。其中,InvocationHandler是一個接口户辫,可以通過實現(xiàn)該接口定義橫切邏輯渐夸,并通過反射機制調(diào)用目標類的代碼,動態(tài)地將橫切邏輯和業(yè)務邏輯編織在一起渔欢。而Proxy利用InvocationHandler動態(tài)創(chuàng)建一個符合某一接口的實例墓塌,生成目標類的代理對象。

只需要一個代理類奥额,而不是針對每個類編寫代理類苫幢。
1、在上一個示例中修改代理類 UserDaoProxy 如下:
JDK動態(tài)代理需要實現(xiàn) InvocationHandler 接口, 這個類其實應該是攔截器類

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 攔截器:
 *      1. 目標類導入
 *      2. 事務導入
 *      3. invoke完成:
 *          1.開啟事務
 *          2.調(diào)用目標對象方法
 *          3.事務提交
 */
public class UserDaoProxy implements InvocationHandler {
    private Object target;
    private Transaction transaction;


    public UserDaoProxy(Object target, Transaction transaction) {
        this.target = target;
        this.transaction = transaction;
    }

    /**
     * 當用戶調(diào)用對象中的每個方法時都通過下面的方法執(zhí)行垫挨,方法必須在接口
     * proxy 被代理后的對象
     * method 將要被執(zhí)行的方法信息(反射)
     * args 執(zhí)行方法時需要的參數(shù)
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        if (!methodName.equals("getUser")){
            this.transaction.beginTransaction();
            method.invoke(target, args); // 目標對象調(diào)用目標方法
            this.transaction.commitTransaction();
        } else {
            method.invoke(target, args);
        }
        return null;
    }

    /**
     * 獲得被代理后的對象
     * @param object  被代理的對象
     * @return  代理后的對象
     * loader:一個ClassLoader對象韩肝,定義了由哪個ClassLoader對象來生成代理對象進行加載
     * interfaces:一個Interface對象的數(shù)組,表示的是我將要給我需要代理的對象提供一組什么接口九榔,如果我提供了一組接口給它哀峻,那么這個代理對象就宣稱實現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了
     * h:一個InvocationHandler對象哲泊,表示的是當我這個動態(tài)代理對象在調(diào)用方法的時候谜诫,會關(guān)聯(lián)到哪一個InvocationHandler對象上,間接通過invoke來執(zhí)行
     */
    public Object getProxyObject(Object object){
        this.target = object;
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(), //類加載器
                target.getClass().getInterfaces(),//獲得被代理對象的所有接口
                this);  //攔截器: InvocationHandler對象
    }
}

2攻旦、測試一下:

public class JDKProxyTest {
    @Test
    public void testProxy(){
        /*
            1. 創(chuàng)建一個目標類
            2. 創(chuàng)建一個事務
            3. 創(chuàng)建一個攔截器
            4. 動態(tài)產(chǎn)生代理對象
         */
        Object target = new UserDaoImpl();
        Transaction transaction = new Transaction();
        List<Interceptor> interceptorList = new ArrayList<>();
        interceptorList.add(transaction);
        UserDaoProxy interceptor = new UserDaoProxy(target, transaction);

      UserDao dao = (UserDao) interceptor.getProxyObject(target);
        dao.delete("10");
    }
}

使用內(nèi)置的Proxy實現(xiàn)動態(tài)代理有一個問題:被代理的類必須實現(xiàn)接口,未實現(xiàn)接口則沒辦法完成動態(tài)代理生逸。
如果項目中有些類沒有實現(xiàn)接口牢屋,則不應該為了實現(xiàn)動態(tài)代理而刻意去抽出一些沒有實例意義的接口,通過cglib可以解決該問題槽袄。

4.1.3 CGLIB動態(tài)代理

CGLIB(Code Generation Library)是一個開源項目,是一個強大的烙无,高性能,高質(zhì)量的Code生成類庫遍尺,它可以在運行期擴展Java類與實現(xiàn)Java接口截酷,通俗說cglib可以在運行時動態(tài)生成字節(jié)碼。
1乾戏、引用 cglib jar 包迂苛,通過maven或者直接下載 jar 包添加

CGLIB jars

下載地址: http://download.csdn.net/download/javawebxy/6849703
maven:<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>

2、修改 攔截器類

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

/*
 * 動態(tài)代理類
 * 實現(xiàn)了一個方法攔截器接口
 */
public class MyInterceptor implements MethodInterceptor {
    // 被代理對象
    private Object target;
    private Transaction transaction;

    public MyInterceptor(Transaction transaction) {
        this.transaction = transaction;
    }

    //動態(tài)生成一個新的類鼓择,使用父類的無參構(gòu)造方法創(chuàng)建一個指定了特定回調(diào)的代理實例
    public Object getProxyObject(Object object) {
        this.target = object;
        // 代碼增強類
        Enhancer enhancer = new Enhancer();
        // 回調(diào)方法
        enhancer.setCallback(this); // 參數(shù)就是攔截器
        //設(shè)置生成類的父類類型
        enhancer.setSuperclass(target.getClass());// 生成的代理類父類是目標類
        //動態(tài)生成字節(jié)碼并返回代理對象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        this.transaction.beginTransaction();
        method.invoke(target, objects);
        this.transaction.commitTransaction();
        return null;
    }
}

3三幻、測試

/**
 * 通過 CGLIB 產(chǎn)生的代理類是目標類的子類
 */
public class CGLIBProxyTest {
    @Test
    public void testCGLIB(){
        Object target = new UserDaoImpl();
        Transaction transaction = new Transaction();
        MyInterceptor interceptor = new MyInterceptor(transaction);

       UserDaoImpl dao = (UserDaoImpl) interceptor.getProxyObject(target);
       dao.insertUser();

        //另一個被代理的對象,不再需要重新編輯代理代碼
        PersonDaoImpl personDao = (PersonDaoImpl) interceptor.getProxyObject(new PersonDaoImpl());
        personDao.delete();
    }
}

4.2 AOP編程

4.2.1概念

使用 JDK 動態(tài)代理的代碼進行對應說明
1. Aspect(切面)
比如說事務、權(quán)限等呐能,與業(yè)務邏輯沒有關(guān)系的部分

切面

2. joinPoint(連接點)
目標類的目標方法念搬。(由客戶端在調(diào)用的時候決定)

連接點

3. pointCut(切入點)
所謂切入點是指我們要對那些攔截的方法的定義.
被納入spring aop中的目標類的方法。

4. Advice(通知)
所謂通知是指攔截到j(luò)oinpoint之后所要做的事情就是通知.通知分為前置通知,后置通知,異常通知,最終通知,環(huán)繞通知(切面要完成的功能)

通知

5. Target(目標對象)
代理的目標對象
6. Weaving(織入)
是指把切面應用到目標對象來創(chuàng)建新的代理對象的過程.切面在指定的連接點織入到目標對象

對比表格查看

JDKProxy代理 SpringAop
目標對象 目標對象 Target
攔截器類 切面 Aspect
攔截器類中的方法 通知 Advice
被攔截到的目標類中方法的集合 切入點 pointCut
在客戶端調(diào)用的方法(目標類目標方法) 連接點 joinPoint
代理類 AOP代理 AOP Proxy
代理類的代理方法生成的過程 織入 Weaving

4.2.2 Spring AOP實現(xiàn)的兩種模式

4.2.2.1 xml形式

還以事務為例, 準備 Transaction 切面類, 目標接口類 UserDao, 目標類 UserDaoImpl

/**
 * 切面
 */
public class Transaction {
    public void beginTransaction(){
        System.out.println("Begin Transaction");
    }

    public void commit(){
        System.out.println("Commit Transaction");
    }
}

- - - - - - - -


public interface UserDao {
    void saveUser();
}

- - - - - - - -

public class UserDaoImpl implements UserDao {
    @Override
    public void saveUser() {
        System.out.println("save Person");
    }
}

剩余的我們需要配置 appliactionContext.xml

1、引入 aop 命名空間

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd" >

2朗徊、配置 兩個 bean

<bean id="userDao" class="com.lanou.spring.aop.transaction.UserDaoImpl"/>
<bean id="transaction" class="com.lanou.spring.aop.transaction.Transaction"/>

3首妖、aop 的配置

<!-- aop 配置-->
<aop:config>
    <!-- 切入點表達式, 確認目標類 -->
    <aop:pointcut id="pointcut" expression="execution(* com.lanou.spring.aop.transaction.UserDaoImpl.*(..))"/>
    <!-- ref 指向的對象就是切面 -->
    <aop:aspect ref="transaction">
        <!-- 前置通知-->
        <aop:before method="beginTransaction" pointcut-ref="pointcut" />
        <!-- 正常返回通知-->
        <aop:after-returning method="commit" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>

4、測試

public class TransactionTest {
    @Test
    public void testTransaction(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) context.getBean("userDao");
        userDao.saveUser();
    }
}

5爷恳、報錯, Spring缺少 aspectjweaver.jar 包, 添加 jar 包重新運行

Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 70 more

Spring AOP 原理:

  1. 當spring容器啟動的時候有缆,加載兩個bean,對兩個bean進行實例化
  2. 當spring容器對配置文件解析到<aop:config>的時候
  3. 把切入點表達式解析出來,按照切入點表達式匹配spring容器內(nèi)容的bean
  4. 如果匹配成功舌仍,則為該bean創(chuàng)建代理對象
  5. 當客戶端利用context.getBean獲取一個對象時妒貌,如果該對象有代理對象,則返回代理對象; 如果沒有代理對象铸豁,則返回對象本身
  6. 切入點表達式如與springbean 沒有一個匹配就會報錯

4.2.2.2 注解形式

  1. 首先需要導入兩個 jar 包 : aspectjrt & aspectjweaver . 需要注意如果你的 jdk 是1.7 就找這兩個 jar 包的1.7.+版本; 我是jdk1.8, 使用了aspectjrt1.8.5 & aspectjweaver1.8.5
  2. 在 applicationContext.xml 中添加context, aop 的命名空間.掃描, 添加自動創(chuàng)建代理設(shè)置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd" >

    <!-- 掃描包 -->
    <context:component-scan base-package="com.lanou.transaction"/>
    <!-- 自動創(chuàng)建代理 -->
    <aop:aspectj-autoproxy/>
</beans>
  1. 添加 UserDaoImpl, Transaction 的注解
@Repository("userDao")
public class UserDaoImpl implements UserDao {...}
--------
@Component
public class Transaction {...}
  1. 在 Transaction 切面類中添加注解
@Component
@Aspect
public class Transaction {
    @Pointcut("execution(* com.lanou.transaction.UserDaoImpl.*(..))")
    private void method(){} //方法簽名
    
    @Before("method()")
    public void beginTransaction(JoinPoint joinpoint){
        System.out.println("Begin Transaction");
    }
    
    @AfterReturning(value = "method()", returning = "returnVal")
    public void commit(JoinPoint joinpoint, Object returnVal)
    {
        System.out.println("返回值: " + returnVal);
        System.out.println("Commit Transaction");
    }

    @After("method()")
    public void finallyMethod(JoinPoint joinpoint){
        System.out.println("Finally Method");
    }

    @AfterThrowing(value = "method()", throwing = "throwable")
    public void throwingMethod(JoinPoint joinpoint, Throwable throwable){
        System.out.println("異常: " + throwable.getMessage());
    }
}

4.2.3 切入點表達式

屏幕快照 2017-06-08 下午4.38.24.png
execution(public * *(..)) :  任意公共方法的執(zhí)行
execution(* set*(..))  : 任何一個名字以 set 開始的方法的執(zhí)行
execution(* com.lanou.spring.aop.transaction.service.*.*(..))  :  在 service 包中定義的任意方法的執(zhí)行
execution(* com.lanou.spring.transaction.service..*.*(..))  :  在 service 包或其子包中定義的任意方法的執(zhí)行
execution(* com.lanou.spring.aop..service..*.*(..))  : 在 aop 包及子包一直到 service 包,再子包下的所有類所有方法 

4.2.4 通知

4.2.4.1 通知種類

名稱 解釋 使用
前置通知
[Before advice]
在連接點前面執(zhí)行灌曙,前置通知不會影響連接點的執(zhí)行,
除非此處拋出異常
<aop:before method="before" pointcut-ref="pointcut"/>
正常返回通知
[After returning advice]
在連接點正常執(zhí)行完成后執(zhí)行节芥,
如果連接點拋出異常在刺,則不會執(zhí)行
<aop:after-returning method="afterReturning" pointcut-ref="pointcut"/>
異常返回通知
[After throwing advice]
在連接點拋出異常后執(zhí)行 <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut"/>
返回通知
[After (finally) advice]
在連接點執(zhí)行完成后執(zhí)行,
不管是正常執(zhí)行完成头镊,還是拋出異常蚣驼,都會執(zhí)行返回通知中的內(nèi)容
<aop:after method="after" pointcut-ref="pointcut"/>
環(huán)繞通知
[Around advice]
環(huán)繞通知圍繞在連接點前后,比如一個方法調(diào)用的前后相艇。
這是最強大的通知類型颖杏,能在方法調(diào)用前后自定義一些操作。
環(huán)繞通知還需要負責決定目標方法的執(zhí)行
<aop:around method="around" pointcut-ref="pointcut"/>

4.2.4.2 通知使用細節(jié)

  1. 前置通知: 每種通知都能夠添加連接點參數(shù), 可以獲取連接點信息
/*
    前置通知
        1.在目標方法執(zhí)行之前執(zhí)行
        2.獲取不到目標方法返回值
 */
public void beginTransaction(JoinPoint joinpoint){
    System.out.println("連接點名稱: "+joinpoint.getSignature().getName());
    System.out.println("目標類" + joinpoint.getTarget().getClass());

    System.out.println("Begin Transaction");
}
  1. 后置通知可以獲取返回值類型, 但當目標方法產(chǎn)生異常, 后置通知將不再執(zhí)行
public class UserDaoImpl implements UserDao {
       @Override
       public String saveUser() {
           /*  制造異常
               int a = 1/0;
           */
           System.out.println("save User");
           return "11111111";
       }
}
 <!-- 正常返回通知
        1. 可以獲取目標方法的返回值
        2. 當目標方法產(chǎn)生異常, 后置通知將不再執(zhí)行
   -->
   <aop:after-returning method="commit" pointcut-ref="pointcut" returning="returnVal"/>
</aop:aspect>
/*
   后置通知, 在目標方法執(zhí)行之后執(zhí)行, 返回值參數(shù)的名稱與 xml 中保護一致
*/
public void commit(JoinPoint joinpoint, Object returnVal){
       System.out.println("目標方法返回值: " + returnVal);
       System.out.println("Commit Transaction");
}
  1. 最終通知
/*
   最終通知
   無論目標方法是否發(fā)出異常都將執(zhí)行
*/
public void finallyMethod(JoinPoint joinpoint){
   System.out.println("Finally Method");
}
<!-- 最終通知 -->
<aop:after method="finallyMethod" pointcut-ref="pointcut"/>
  1. 異常通知
/*
    異常通知
    接受目標方法拋出的異常
 */
public void throwingMethod(JoinPoint joinPoint, Throwable throwable){
    System.out.println("異常: " + throwable.getMessage());
}
<!--異常通知-->
<aop:after-throwing method="throwingMethod" pointcut-ref="pointcut" throwing="throwable"/>
  1. 環(huán)繞通知
/*
    環(huán)繞通知
    ProceedingJoinPoint: 子接口
    控制目標方法的執(zhí)行
    前置通知和后置通知也能在目標方法的前后添加內(nèi)容,但是不能控制目標方法的執(zhí)行
 */
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("before..before..before");
    joinPoint.proceed(); // 調(diào)用目標方法
    System.out.println("after..after.after");
}
<!-- 環(huán)繞通知 -->
    <aop:around method="around" pointcut-ref="pointcut"/>
</aop:aspect>

4.2.5 SpringAOP 細節(jié)

  1. 如果目標類實現(xiàn)了接口, 則采用 JDKProxy; 如果沒有實現(xiàn)接口, 采用 CGLIBProxy [Spring 內(nèi)部做的]
  2. 目標類實現(xiàn)了接口, 但還想要采用 CGLIBProxy, 作如下更改:

Spring4.3.8學習之 與 Struts2 整合[四]
Spring4.3.8學習之與Hibernate4 整合[五]
Spring4.3.8學習之S2SH 整合[六]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坛芽,一起剝皮案震驚了整個濱河市留储,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咙轩,老刑警劉巖获讳,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異活喊,居然都是意外死亡丐膝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門钾菊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帅矗,“玉大人,你說我怎么就攤上這事结缚∷鹞睿” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵红竭,是天一觀的道長尤勋。 經(jīng)常有香客問我喘落,道長,這世上最難降的妖魔是什么最冰? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任瘦棋,我火速辦了婚禮,結(jié)果婚禮上暖哨,老公的妹妹穿的比我還像新娘赌朋。我一直安慰自己,他們只是感情好篇裁,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布沛慢。 她就那樣靜靜地躺著,像睡著了一般达布。 火紅的嫁衣襯著肌膚如雪团甲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天黍聂,我揣著相機與錄音躺苦,去河邊找鬼。 笑死产还,一個胖子當著我的面吹牛匹厘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脐区,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼愈诚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了牛隅?” 一聲冷哼從身側(cè)響起扰路,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倔叼,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宫莱,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡丈攒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了授霸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巡验。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碘耳,靈堂內(nèi)的尸體忽然破棺而出显设,到底是詐尸還是另有隱情,我是刑警寧澤辛辨,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布捕捂,位于F島的核電站瑟枫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏指攒。R本人自食惡果不足惜慷妙,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望允悦。 院中可真熱鬧膝擂,春花似錦、人聲如沸隙弛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽全闷。三九已至叉寂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間室埋,已是汗流浹背办绝。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姚淆,地道東北人孕蝉。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像腌逢,于是被迫代替她去往敵國和親降淮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

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

  • 從三月份找實習到現(xiàn)在搏讶,面了一些公司佳鳖,掛了不少,但最終還是拿到小米媒惕、百度系吩、阿里、京東妒蔚、新浪穿挨、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,192評論 11 349
  • 一> 代理模式 概述 代理(Proxy)是一種設(shè)計模式肴盏, 提供了對目標對象另外的訪問方式科盛;即通過代理訪問目標對象。...
    奮斗的老王閱讀 1,101評論 0 50
  • **** AOP 面向切面編程 底層原理 代理2嗽怼U昝唷! 今天AOP課程1恍飘、 Spring 傳統(tǒng) AOP2榨崩、 Spri...
    luweicheng24閱讀 1,355評論 0 1
  • 我不是一個能吃苦的人谴垫,那種腐朽的生活方式我也羨慕,我也想按自己的生活方式去過自己的一生蜡饵,我的工作雖不說能讓我大富...
    時光豬閱讀 444評論 0 0
  • 有的人不喜歡校服溯祸,認為無法顯示自己的個性肢专;有的人不喜歡校服,所以喜歡在上面涂鴉焦辅;有的人則喜歡自己動手修剪校服……可...
    紫霞Candice閱讀 865評論 0 1