zoukankan      html  css  js  c++  java
  • 笔记12 注入AspectJ切面

    虽然Spring AOP能够满足许多应用的切面需求,但是与AspectJ相比, Spring AOP 是一个功能比较弱的AOP解决方案。AspectJ提供了Spring AOP所不能支持的许多类型的切点。

    但是精心设计且有意义的切面很可能依赖其他类来完成它们的工作。 如果在执行通知时,切面依赖于一个或多个类,我们可以在切面内部 实例化这些协作的对象。但更好的方式是,我们可以借助Spring的依 赖注入把bean装配进AspectJ切面中。

    我们为演出创建一个新切面。具体来讲,我们以切面的方式创建一个评论员的角色,他会观看演出并且会在演出之后提 供一些批评意见。

    在此我们给出完整的代码。首先必须为myeclipse安装AspectJ插件,可以参考:https://blog.csdn.net/qq_35592011/article/details/71602026,安装完成后创建一个AspectJ项目。

    1.表演接口Performance.java

    1 package concert4;
    2 
    3 public interface Performance {
    4     public void perform();
    5 }

    2.表演实现类Classcial.java

     1 package concert4;
     2 
     3 public class Classcial implements Performance {
     4 
     5     @Override
     6     public void perform() {
     7         // TODO Auto-generated method stub
     8         System.out.println("我是古典音乐会!");
     9     }
    10 
    11 }

    3.观众类(切面)Audience.java

     1 package concert4;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 
     5 public class Audience {
     6 
     7     // ProceedingJoinPoint作为参数。
     8     // 这个对象是必须要有的,因为 你要在通知中通过它来调用被通知的方法。
     9     // 通知方法中可以做任何的 事情,当要将控制权交给被通知的方法时,它需要调 用ProceedingJoinPoint的proceed()方法。
    10     public void watchPerformance(ProceedingJoinPoint jp) {
    11         try {
    12             System.out.println("Silencing cell phone");
    13             System.out.println("Taking seats");
    14             jp.proceed();
    15             System.out.println("CLAP CLAP CLAP");
    16         } catch (Throwable e) {
    17             System.out.println("Demanding a refund");
    18         }
    19     }
    20 }

    4.附加表演接口Encoreable.java

    1 package concert4;
    2 
    3 public interface Encoreable {
    4     void performEncore();
    5 }

    5.附加表演实现类DefaultEncoreable.java

     1 package concert4;
     2 
     3 public class DefaultEncoreable implements Encoreable {
     4 
     5     @Override
     6     public void performEncore() {
     7         // TODO Auto-generated method stub
     8         System.out.println("川剧变脸");
     9     }
    10 
    11 }

    6.创建评论切面CriticAspect.java

    CriticAspect的主要职责是在表演结束后为表演发表评论。其中的performance()切点匹配perform()方法。当它 与after()returning通知一起配合使用时,我们可以让该切面在 表演结束时起作用。

    需要注意的是整个过程并不是评论员自己发表评论,实际 上,CriticAspect与一个CriticismEngine对象相协作,在表 演结束时,调用该对象的getCriticism()方法来发表一个苛刻的 评论。为了避免CriticAspect和CriticismEngine之间产生不 必要的耦合,我们通过Setter依赖注入为CriticAspect设 置CriticismEngine。下图展示了此关系:

     1 package concert4;
     2 
     3 public aspect CriticAspect {
     4     public CriticAspect(){}
     5     pointcut performance():execution(* perform(..));
     6     after()returning :performance(){
     7         System.out.println("--------------评论----------------");
     8         System.out.println(criticismEngine.getCriticism());
     9         System.out.println("----------------------------------");
    10     }
    11     
    12     private CriticismEngine criticismEngine;
    13     
    14     public void setCriticismEngine(CriticismEngine criticismEngine){
    15         this.criticismEngine=criticismEngine;
    16     }
    17 }

    7.创建评论员接口CriticismEngine.java

    1 package concert4;
    2 
    3 public interface CriticismEngine {
    4     public String getCriticism();
    5 }

    8.实现评论员接口CriticismEngineTmpl.java(要注入到CriticAspect中的CriticismEngine实现

     1 package concert4;
     2 
     3 public class CriticismEngineTmpl implements CriticismEngine {
     4 
     5     private String[] criticismPool;
     6 
     7     public void setCriticismPool(String[] criticismPool) {
     8         this.criticismPool = criticismPool;
     9     }
    10 
    11     public CriticismEngineTmpl() {
    12     }
    13 
    14     @Override
    15     public String getCriticism() {
    16         // TODO Auto-generated method stub
    17         int i = (int) (Math.random() * criticismPool.length);
    18         return criticismPool[i];
    19     }
    20 
    21 }

    CriticismEngineImpl实现了CriticismEngine接口,通过从 注入的评论池中随机选择一个苛刻的评论。要将这个类在XML文档中声明为一个bean。

    9.XML配置文件

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:aop="http://www.springframework.org/schema/aop"
     5     xmlns:tx="http://www.springframework.org/schema/tx"
     6     xmlns:context="http://www.springframework.org/schema/context"
     7     xmlns:c="http://www.springframework.org/schema/c"
     8     xsi:schemaLocation="
     9    http://www.springframework.org/schema/beans
    10    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    11    http://www.springframework.org/schema/aop
    12    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    13    http://www.springframework.org/schema/tx
    14    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    15    http://www.springframework.org/schema/context     
    16    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    17            
    18         <bean class="concert4.Classcial"></bean>
    19         <bean id="audience" class="concert4.Audience"></bean>
    20         <bean id="criticismEngine" class="concert4.CriticismEngineTmpl">
    21             <property name="criticismPool">
    22                 <list>
    23                     <value>不好</value>
    24                     <value>很不好</value>
    25                     <value>非常不好</value>
    26                 </list>
    27             </property>
    28         </bean>
    29         <bean class="concert4.CriticAspect" factory-method="aspectOf">
    30             <property name="criticismEngine" ref="criticismEngine"></property>
    31         </bean>
    32            <aop:config>
    33                    <aop:aspect ref="audience">
    34                        <aop:pointcut expression="execution(* concert4.Performance.perform(..))" id="performance"/>
    35                        <aop:around method="watchPerformance" pointcut-ref="performance"/>
    36                        <aop:declare-parents types-matching="concert4.Performance+" 
    37                                             implement-interface="concert4.Encoreable" 
    38                                             default-impl="concert4.DefaultEncoreable"/>
    39                    </aop:aspect>
    40            </aop:config>
    41    </beans>

      需要注意的是,在为CriticAspect装配CriticismEngineImple之前,我们必须清楚AspectJ切面根本不需要 Spring就可以织入到我们的应用中。如果想使用Spring的依赖注入为 AspectJ切面注入协作者,那我们就需要在Spring配置中把切面声明为 一个Spring配置中的<bean>。

      但是在配置过程中使用了特殊的factorymethod属性。通常情况下,Spring bean由Spring容器初始化,但是 AspectJ切面是由AspectJ在运行期创建的。等到Spring有机会 为CriticAspect注入CriticismEngine时,CriticAspect已 经被实例化了。 因为Spring不能负责创建CriticAspect,那就不能在 Spring中简单 地把CriticAspect声明为一个bean。我们需要一种方式为 Spring获得已经由AspectJ创建的CriticAspect实例的句柄,从而可 以注入CriticismEngine。的AspectJ切面都提供了一 个静态的aspectOf()方法,该方法返回切面的一个单例。所以为了 获得切面的实例,我们必须使用factory-method来调 用asepctOf()方法而不是调用CriticAspect的构造器方法。 

      简而言之,Spring不能像之前那样使用<bean>声明来创建一 个CriticAspect实例——它已经在运行时由AspectJ创建完成了。 Spring需要通过aspectOf()工厂方法获得切面的引用,然后像 <bean>元素规定的那样在该对象上执行依赖注入。 

    10.测试类ConcertTest.java

     1 package concert4;
     2 
     3 import org.junit.Test;
     4 import org.junit.runner.RunWith;
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.test.context.ContextConfiguration;
     7 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     8 
     9 @RunWith(SpringJUnit4ClassRunner.class)
    10 // @ContextConfiguration(classes = concert3.ConcertConfig.class)
    11 @ContextConfiguration("classpath:ConcertConfig6.xml")
    12 public class ConcertTest {
    13     @Autowired
    14     public Performance p;
    15     @Autowired
    16     public Encoreable en;
    17 
    18     @Test
    19     public void test() {
    20 
    21         p.perform();
    22         System.out.println("-----------------------------");
    23         System.out.println("自己创建对象调用");
    24         en.performEncore();
    25         System.out.println("-----------------------------");
    26         System.out.println("通过Performance对象调用“新方法”");
    27         Encoreable e = (Encoreable) p;
    28         e.performEncore();
    29     }
    30 }

    11.结果(有疑问!!!!!!!!!!)

  • 相关阅读:
    I.MX6 Parallel RGB LCD Datasheet描述
    ubuntu IP 扫描
    I.MX6 按键开关机 PMIC 检测
    java中对List中对象排序实现
    jQuery实现父窗口的问题
    如何在Oracle中复制表结构和表数据
    handsontable常规配置的中文API
    oracle中to_date详细用法示例(oracle日期格式转换)
    js中子页面父页面方法和变量相互调用
    关于Ajax的type为post提交方式出现请求失效问题
  • 原文地址:https://www.cnblogs.com/lyj-gyq/p/8903878.html
Copyright © 2011-2022 走看看