利用例子来理解spring的面向切面编程(使用@Aspect)

上篇的例子,自动装配和自动检测Bean是使用注解的方式处理的,而面向切面编程是使用aop标签处理的,给我感觉就像中西医参合一样。

现在就来优化优化,全部使用注解的方式处理。

1、工程图:

 


 

 2、Protecter的修改如下,Protecter声明了切点和通知,因此不需要在xml中配置切点和通知了。

package com.test.demo.protect;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.test.demo.stolen.Peaces;

/**
 * 守护者,是一个切面
 * TODO Comment of Protecter
 *
 
*/
@Component("protecter")
@Aspect
public class Protecter {
    @Pointcut("execution(* com.test.demo.stolen.Stolen.stolens(String,com.test.demo.stolen.Peaces)) and args(name,peace)")
    //stolens()是切点的一个名称,类似于xml配置时指定的id一样
    public void stolens(){
    }

    @Before("stolens() && args(name,peace)")
    public void before(String name,Peaces peace){
        System.out.println("守护者在守护桃子"+peace.getName()+"...");
    }
    
    @After("stolens() && args(name,peace)")
    public void after(String name,Peaces peace){
        System.out.println("守护者发现猴子"+name+"在偷桃子"+peace.getName());
    }
}

 2、Stolen 接口,未做任何修改:

package com.test.demo.stolen;

public interface Stolen {
    /**
     * 偷桃子
     * 
     * @date 2014-4-1
     
*/
    public void stolens(String name,Peaces peace);
}
View Code

 3、Monkey实现Stolen接口,未做修改:

package com.test.demo.stolenImpl;

import org.springframework.stereotype.Component;

import com.test.demo.stolen.Peaces;
import com.test.demo.stolen.Stolen;

/**
 * 猴子偷桃子
 * TODO Comment of Monkey
 *
 
*/
@Component("monkey")
public class Monkey implements Stolen{

    private String name;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void stolens(String name,Peaces peace){
        System.out.println("猴子 "+name+" 正在偷桃子,桃子是:"+peace.getName()+" 大小:"+peace.getType());
        this.name = name;
    }
}
View Code

 

 4、现在需要让Spring将Protecter应用成为一个切面。这个需要在Spring上下文中声明一个自动代理Bean。Spring中有个自动代理创建类:AnnotationAwareAspectJAutoProxyCreator.

这个类会代理一些Bean,这些Bean的方法需要与@AspectJ注解的Bean中所定义的切点相匹配。

在本例中,则表示:

AnnotationAwareAspectJAutoProxyCreator这个自动代理Bean,会找到使用@AspectJ注解的Bean。Protecter类使用了注解

@Component("protecter") :会自动将Protecter类检测为Bean
@Aspect:@AspectJ注解

因此,Protecter类满足了使用@AspectJ注解的Bean这个要求,@AspectJ注解的Bean中所定义的切点相匹配,这表示会找到Protecter类中定义的切点:

 

@Pointcut("execution(* com.test.demo.stolen.Stolen.stolens(String,com.test.demo.stolen.Peaces)) and args(name,peace)")

 

与这个切点相匹配的则是com.test.demo.stolen.Stolen.stolens(name,peace) 这个方法了。

 

所以,本例中AnnotationAwareAspectJAutoProxyCreator类会自动代理实现了接口Stolen的Bean.即Monkey类。

 

Spring为了简化声明,Spring在aop命名空间中更为简洁的声明方式为:

<aop:aspectj-autoproxy />

 

<aop:aspectj-autoproxy />会在Spring上下文中声明一个AnnotationAwareAspectJAutoProxyCreator类。

 

beans.xml:

<?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-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"

        default-autowire
="byName">

    <!-- 注解,自动装配bean -->
    <context:annotation-config />
    <!-- 自动检测Bean -->
    <context:component-scan base-package="com.test"></context:component-scan>
    <!-- 自动代理Bean -->
    <aop:aspectj-autoproxy />    
</beans>


 测试类及运行结果:

package com.test.demo;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.demo.stolen.Peaces;
import com.test.demo.stolen.Stolen;


public class MonkeyStokenTest {
    
    @Test
    public void testStolen() {
     ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
         Stolen m = (Stolen)ctx.getBean("monkey");
         Peaces p = new Peaces();
         p.setName("水蜜桃");
         p.setType("BIG");
         m.stolens("小小",p);
    }
}

 

 

 

posted @ 2014-04-03 10:01  爱生活者wmmang  Views(552)  Comments(0Edit  收藏  举报