虽然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 ????@Override15 ????public String getCriticism() {16 ????????// TODO Auto-generated method stub17 ????????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/beans10 ???http://www.springframework.org/schema/beans/spring-beans-3.0.xsd11 ???http://www.springframework.org/schema/aop12 ???http://www.springframework.org/schema/aop/spring-aop-3.0.xsd13 ???http://www.springframework.org/schema/tx14 ???http://www.springframework.org/schema/tx/spring-tx-3.0.xsd15 ???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 ????@Autowired14 ????public Performance p;15 ????@Autowired16 ????public Encoreable en;17 18 ????@Test19 ????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.结果(有疑问!!!!!!!!!!)
笔记12 注入AspectJ切面
原文地址:https://www.cnblogs.com/lyj-gyq/p/8903878.html