Spring4.3使用注解创建切面
Posted Java全栈从0到1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring4.3使用注解创建切面相关的知识,希望对你有一定的参考价值。
AspectJ5之前,编写AspectJ切面需要学习一种Java语言的扩展。
AspectJ5引入了使用注解来创建切面的关键特性,AspectJ面向注解的模型可以非常简便地通过注解把任意类转变为切面。
1、定义切面
@Aspect public class Audience{ //表演前 @Before("execution(** concert.Performance.perform(..))") public void silenceCellPhones(){ System.out.println("Silencing cell phones"); } //表演前 @Before("execution(** concert.Performance.perform(..))") public void takeSeats(){ System.out.println("Taking seats"); } //表演后 @AfterReturning("execution(** concert.Performance.perform(..))") public void applause(){ System.out.println("Clap!!"); } //表演失败后 @AfterThrowing("execution(** concert.Performance.perform(..))") public void demandRefund(){ System.out.println("Refund!!"); } }
@Aspect注解表示Audience不仅是一个POJO,还是一个切面。
@Before,@AfterReturning等注解,用来声明通知方法。
使用@Pointcut注解定义可重用切点
@Aspect public class Audience{ //可重用切点 @Pointcut("excution(** concert.performance.perform(..))") public void performance(){} //表演前 @Before("performance()") public void silenceCellPhones(){ System.out.println("Silencing cell phones"); } //表演前 @Before("performance()") public void takeSeats(){ System.out.println("Taking seats"); }
使用一个空的方法,作为标记,使用@Pointcut注解定义成一个可重用的节点,然后通过“方法名()”来进行引用
启用自动代理
以上仅仅是定义了切面,要启动切面功能,需要启动切面的代理
Java配置方法
@Configuration @EnableAspectJAutoProxy//启动AspectJ自动代理 @ComponentScan public class ConcertConfig{ @Bean Public Audience audience(){//声明Audience bean return new Audience(); } }
XML配置方法(使用aop命名空间)
<?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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-beans.xsd"> <context:conponent-scan base-package="concert" /> <!-- 启用AspectJ自动代理 --> <aop:aspectj-autoproxy /> <!-- 声明Audience bean --> <bean class="concert.Audience" /> </beans>
代理的作用
使用上述2种方法,会给Concert bean创建一个代理,Audence类中的通知方法会在perform()调用前后执行。
注意!Spring的AspectJ自动代理仅仅使用@AspectJ作为创建切面的知道,切面本质上还是Spring基于代理的切面,仅局限于代理方法的调用。
如果想要使用AspectJ的所有能力,必须运行时使用AspectJ并且不依赖Spring。
2、创建环绕通知
@Aspect public class Audience{ //可重用切点 @Pointcut("excution(** concert.performance.perform(..))") public void performance(){} //环绕通知方法 @Around("performance()") public void watchPerformance(ProceedingJoinPoint jp){ try{ System.out.println("Silencing cell phones"); System.out.println("Taking seats"); jp.proceed(); System.out.println("CLAP!!"); }catch(Throwable e){ System.out.println("refund!!"); } } }
可以将前置和后置通知写在一个方法中,并使用ProceedingJoinPoint对象来进行对目标方法的调用。
3、处理通知中的参数
@Aspect public class TrackCounter{ private Map<Interger,Integer> trackCounts = new HashMap<Integer,Integer>(); @Pointcut( "execution(* soundsystem.CompactDisc.playTrack(int))" + "&& args(trackNumber)") public void trackPlayed(int trackNumber){} @Before("trackPlayed(trackNumber)") public void countTrrack(int trackNumber){ int currentCount = getPlayCount(trackNumber); trackCounts.put(trackNumber,currentCount + 1); } public int getPlayCount(int trackNumber){ return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0; } }
4、通过注解引入新功能
假设情景:有一个类,希望让其以及其实例实现某个接口,但这个类是不可以修改的(如没有源码)。我们可以通过AOP为这个类引入新的方法,实现该接口。
例如
我们有一个类concert.Performance
希望能通过AOP实现接口
public interface Encoreable{ void performEncore(); }
切面
@Aspect public class EncoreableIntroducer{ @DeclareParents(value="concert.performance+",defaultImpl=DefaultEncoreable.class) public static Encoreable encoreable; }
通过声明一个切面,使用@DeclareParents注解,讲Encoreable接口引入到Performance bean中。
@DeclareParents的组成部分
1、Value属性指定哪种类型bean要引入该接口。本例中,指所有实现Performance的类型。(加号表示是Performance的所有子类型,而不是Performance本身。)
2、defaultImpl属性指定为引入功能提供实现的类。在这里我们指定的是DefaultEncoreable提供实现。
3、@DeclareParents注解所标注的惊天属性知名了要引入的接口。在这里我们引入的是Encoreable接口。
以上是关于Spring4.3使用注解创建切面的主要内容,如果未能解决你的问题,请参考以下文章