系统学习Spring之Spring in action(七)

每日一叨:

    下班回来,没有立即写博客,而是欣赏了之前下载的一部电影<心灵捕手>,静下心来好好欣赏,在这就不剧透啦.

文章导读:

     1.面向切面编程之XML配置

 

知识点:

 

1.面向切面编程之XML配置

在学习面向切面之前,首先理解下AOP中的术语,有助于后面能够更好的理解AOP.

ADVICE:面向切面编程的任务一般被称为ADVICE,Spring有5种ADVICE分别是Before,After,After-returnning,After-throwing,Around.

ADVICE主要的作用是定义了做什么和什么时候做.

JOIN POINTS:面向切面编程可能执行的地方被称为JOIN POINTS.

POINTCUTS:POINTCUTS主要就是缩小JOIN POINTS,系统不可能在所有的JOIN POINTS都进行处理,所以只能用POINTCUTS定义在哪处理.

ASPECTS:ADVICE和POINTCUTS的结合体,ASPECTS定义了要执行什么,在哪执行,什么时候执行.

SpringAOP只支持方法拦截,不支持构造方法和字段的拦截,简单的说就是SpringAOP无法细粒度的拦截字段的修改和bean的创建.

首先用使用通过XML配置来写第一个SpringAOP事例:

建立喝咖啡的类:

public class DrinkCoffee {
    //正在喝咖啡就用这个做例子吧
    public void drink(){
        System.out.println("咖啡好喝极了.");
    }
}

建立咖啡类:

public class Coffee {
    //喝咖啡之前
    public void beforeDrinkCoffee(){
        System.out.println("首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.");
    }
    
    //喝咖啡之后
    public void afterDrinkCoffee(){
        System.out.println("咖啡太好喝了,好想在喝一杯...");
    }
    
    //水放少了,咖啡有点苦.
    public void somethingIsWrong(){
        System.out.println("一不小心把水放多了,味道比较淡,口感欠佳.");
    }
    
    //喝完咖啡要记得洗杯子哦.
    public void washCup(){
        System.out.println("喝完咖啡后洗杯子.");
    }
}

用XML配置的方式来配置SpringAOP:

    <bean id="drinkCoffee" class="com.ricky.zero.pojo.DrinkCoffee"></bean><!-- 实例化DrinkCoffee  --> 
    <bean id="coffee" class="com.ricky.zero.pojo.Coffee"></bean><!-- 实例化Coffee -->
    <aop:config><!-- 配置SpringAOP -->
        <aop:aspect ref="coffee"> <!-- 定义DrinkCoffee实例中,当执行实例中drink方法时执行下面的point -->
            <aop:pointcut expression="execution(* com.ricky.zero.pojo.DrinkCoffee.drink(..))" id="drink"/>
        <!-- 在执行drink之前执行beforeDrinkCoffee -->
<aop:before method="beforeDrinkCoffee" pointcut-ref="drink"/>
       <!-- 无论drink方法执行成功还是抛异常,在drink方法后执行washCup -->
        <
aop:after method="washCup" pointcut-ref="drink"/> <aop:after-throwing method="somethingIsWrong" pointcut-ref="drink"/><!-- 当drink方法抛异常时执行 --> <aop:after-returning method="afterDrinkCoffee" pointcut-ref="drink"/><!-- 当drink方法执行成功时执行 --> </aop:aspect> </aop:config>

运行测试:

        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        DrinkCoffee drinkCoffee  = (DrinkCoffee)ctx.getBean("drinkCoffee");
        drinkCoffee.drink();

测试结果:

首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.

咖啡好喝极了.

喝完咖啡后洗杯子.

咖啡太好喝了,好想在喝一杯...

 

修改DrinkCoffee类,可以看到aop:after-throwing效果:

public class DrinkCoffee {
    //正在喝咖啡就用这个做例子吧
    public void drink(){
        System.out.println("咖啡好喝极了." + 1/0);
    }
}

运行测试并得到结果:

首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.

喝完咖啡后洗杯子.

一不小心把水放多了,味道比较淡,口感欠佳.

当出现异常的时候aop:after-returning不会执行.

 

aop:before和aop:after两个在一起有一个致命的缺点,就是在执行drink方法的时候,before和after方法之间的数据信息是不能共享的.

Spring还提供了一个可以在drink执行前和执行后拦截并且数据可以共享的方法使用<aop:around>标签.

public class DrinkCoffee{
    //正在喝咖啡就是这个做例子吧
    public void drink(){
        System.out.println("咖啡真好喝.");
    }
}
public class Coffee {
    //喝咖啡之前
    public void beforeDrinkCoffee(){
        System.out.println("首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.");
    }
    
    //喝咖啡之后
    public void afterDrinkCoffee(){
        System.out.println("咖啡太好喝了,好想在喝一杯...");
    }
    
    //水放少了,咖啡有点苦.
    public void somethingIsWrong(){
        System.out.println("一不小心把水放多了,味道比较淡,口感欠佳.");
    }
    
    //喝完咖啡要记得洗杯子哦.
    public void washCup(){
        System.out.println("喝完咖啡后洗杯子.");
    }
    
    //把所有步骤都放到一个方法里
    public void allInOne(ProceedingJoinPoint p){
        
        try {
            System.out.println("首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.");
            p.proceed();
            System.out.println("咖啡太好喝了,好想在喝一杯...");
        } catch (Throwable e) {
            // TODO Auto-generated catch block
            System.out.println("一不小心把水放多了,味道比较淡,口感欠佳.");
        }finally{
            System.out.println("喝完咖啡后洗杯子.");
        }
    }
}

 

配置文件:

    <bean id="coffee" class="com.ricky.zero.pojo.Coffee"></bean>
    <bean id="drinkCoffee" class="com.ricky.zero.pojo.DrinkCoffee"></bean>
    <aop:config>
        <aop:aspect ref="coffee">
            <aop:pointcut expression="execution(* com.ricky.zero.pojo.DrinkCoffee.drink(..))" id="drink"/>
            <aop:around method="allInOne" pointcut-ref="drink"/>
        </aop:aspect>
    </aop:config>

 

运行测试:

        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        DrinkCoffee drinkCoffee  = (DrinkCoffee)ctx.getBean("drinkCoffee");
        drinkCoffee.drink();

测试结果:

首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.
咖啡真好喝.
咖啡太好喝了,好想在喝一杯...
喝完咖啡后洗杯子.

 

若drink方法执行时出现异常,例如:

public class DrinkCoffee{
    //正在喝咖啡就是这个做例子吧
    public void drink(){
        System.out.println("咖啡真好喝." + 1/0);
    }
}

运行测试后结果为:

首先把水烧开,把咖啡粉倒入杯中,倒入适量的白开水,然后用勺子搅拌.
一不小心把水放多了,味道比较淡,口感欠佳.
喝完咖啡后洗杯子.

时间不早了,,明天在写吧...

 

--------------------------------申明----------------------------       

                  本文可以免费阅读以及转载,转载时请注明出处.      

                  本人邮箱:Ricky_LS@163.com

                  Thank you for your corporation.

 

posted @ 2013-03-28 01:05  养家糊口  阅读(1201)  评论(0编辑  收藏  举报