Spring实战09——AOP之注入AspectJ切面

回顾一下:

Spring 的四种4种类型的AOP支持:
* 1.基于代理的经典SpringAOP
* 2.纯POJO切面
* 3.@AspectJ注解驱动的切面
* 4.注入式AspectJ切面

前三种都是Spring AOP实现的变体,Spring AOP构建在动态代理之上,因此Spring 对AOP 的支持局限于方法拦截器,Spring 的AOP 无法把通知应用于对象的创建过程(构造方法)。

第四种类型能够将值注入到AspectJ 驱动的切面中。

前面的例子中我们常用@Aspect 来注解一个类,这些切面可能依赖于Spring容器 创建的bean 来完成它们的工作。我们可以借助Spring 的注入依赖把bean 装配到AspectJ 切面中,AspectJ 切面并不依赖于Spring 来创建切面。


场景:评论员对表演员在表演进场时鼓掌表欢迎,在表演员表演后作出评论。

1.表演接口

public interface Performance {
    public void perform();
}

2.表演实现类

public class PerformanceImpl implements Performance {

    //构造方法
    public PerformanceImpl() {
        System.out.println("演员进场...");
    }

    @Override
    public void perform() {
        System.out.println("表演过程中...");
    }
}

 3.评论员接口

public interface CriticismEngine {
    public String getCriticism();
}

 4.实现评论员接口

public class CriticismEngineImpl implements CriticismEngine {

    private String[] criticismPool;//评论池,即评论员的评论集合

    public CriticismEngineImpl(){}

    public void setCriticismPool(String[] criticismPool){
        this.criticismPool = criticismPool;
    }

    /**
     * 随机从评论池中选取一条评论
     */
    @Override
    public String getCriticism() {
        int i = (int) (Math.random() * criticismPool.length);
        return criticismPool[i];
    }
}

5.AspectJ 切面,注意时aspect 类型来声明AspectJ 切面,不是class

public aspect CriticAspect {
    private CriticismEngine criticismEngine;//使用Spring 的依赖注入bean

    public CriticAspect() {}

    pointcut applause(): execution(com.qhf.aop.example08.PerformanceImpl.new());
    after(): applause() {
        System.out.println("评论员鼓掌...");
    }

    pointcut performance(): execution(* com.qhf.aop.example08.Performance.perform(..));
    after(): performance() {
        System.out.println("评论员:" + criticismEngine.getCriticism());
    }

    public void setCriticismEngine(CriticismEngine criticismEngine) {
        this.criticismEngine = criticismEngine;
    }
}

6.配置类

@Configuration//作为配置文件之一
@ImportResource("classpath:aop/example08/aop.xml")
public class AOPConfig {

}

7.xml 配置

通常情况下,Spring bean 由Spring 容器初始化的,但是AspectJ 切面是由AspectJ 在运行期创建的。

bean 的 factory-method 属性,值为 "aspectOf" :所有的AspectJ 切面都提供了一个静态的aspectOf() 方法,该方法返回切面的一个单例。这里有个问题:去除了这个属性,依然能运行“评论员鼓掌...”,但是却不能运行这个切面里的引用对象的方法,说明去除这个属性,Spring 创建的bean 不会装配到AspectJ 切面中,切面却是成功创建。这个问题待研究。。。

<?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.xsd">

    <!-- 启动AspectJ 自动代理 -->
    <aop:aspectj-autoproxy/>

    <!-- bean,注入到aspect 切面中 -->
    <bean id="criticismEngine" class="com.qhf.aop.example08.CriticismEngineImpl">
        <property name="criticismPool">
            <list>
                <value>good</value>
                <value>better</value>
                <value>bad</value>
                <value>worst</value>
            </list>
        </property>
    </bean>

    <!-- factory-method="aspectOf":
    并不是由Spring 创建的bean,而是由AspectJ 在运行期创建的;
    所有的AspectJ 切面都提供了一个静态的aspectOf() 方法,该方法返回切面的一个单例 -->
    <bean class="com.qhf.aop.example08.CriticAspect" factory-method="aspectOf">
        <property name="criticismEngine" ref="criticismEngine"/>
    </bean>

    <!-- 自动注入的bean -->
    <bean id="performanceImp" class="com.qhf.aop.example08.PerformanceImpl" />
</beans>

8.测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= AOPConfig.class)
public class Test {

    @Autowired
    private Performance performance;//即便这里名字是performance,符合这个接口的实现类是PerformanceImpl,所以bean的id是performanceImpl

    @org.junit.Test
    public void test(){
        performance.perform();
    }
}

9.结果:

演员进场...
评论员鼓掌...
表演过程中...
评论员:good

猜你喜欢

转载自blog.csdn.net/pigqhf/article/details/88994166
今日推荐