SpringAOP切点配置(注解与xml配置)

来源:互联网 发布:linux进程数据结构 编辑:程序博客网 时间:2024/06/07 05:26

  本文介绍介绍spring aop 的用法:注解和xml配置,最简洁的配置,最简单的介绍。

注解

  使用注解去配置aop非常的简单,只需要在spring的xml配置文件里激活component-scan功能指定需要扫描的包,将组件都初始化到spring的容器中。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/aop http://www.springframework.org/schema/aop/spring-aop-4.1.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-context-4.1.xsd">    <context:component-scan base-package="com.springinaction"/>    <!-- 激活自动代理功能 -->    <aop:aspectj-autoproxy proxy-target-class="true"/></beans>

  很简单,除了引入spring的一些命名空间外还有两行,一个是注册扫描功能并指定目标包、第二个是注册自动代理功能,这一点很重要,如果你不加入的话,spring就会抛出异常,我小白,没有能搞定其中的原理,在网上找了一个链接
动态代理

编写接口

  这里声明一个接口Performance,里面有perform()方法,如下

package com.springinaction.service;public interface Performance {    public void perform();}

编写Actor实现接口

这里需要加上conponent的注解,是让spring初始化的时候被扫描到

package com.springinaction.service;import org.springframework.stereotype.Component;@Componentpublic class Actor implements Performance {    @Override    public void perform() {        System.out.println("表演中...");    }}

编写一个切面

这个bean除了需要加上component的注解外,还需要加上aspectj的注解,让spring知道他不仅仅是一个组件,而且是一个切面。代码如下

package com.springinaction.aop;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Component@Aspectpublic class AudienceAnnotation {    @Pointcut("execution(** com.springinaction.service.Performance.perform(..))")    public void performance(){}    @Before("performance()")    public void takeSeats(){        System.out.println("找座位");    }    @AfterReturning("performance()")    public void applause(){        System.out.println("再来一个");    }    @AfterThrowing("performance()")    public void demandRefund(){        System.out.println("垃圾,炒鸡垃圾");    }    @Around("performance()")    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{          System.out.println("进入环绕通知");          Object object = pjp.proceed();//执行该方法          System.out.println("退出环绕通知");          return object;      }}

Pointcut注解的performance方法并没有实质性作用,这是为了扩展切点表达式语言,这样就可以在任何切点表达式中使用performance,当然不使用Pointcut你就要这样写

package com.springinaction.aop;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;@Component@Aspectpublic class AudienceAnnotation {    @Before("execution(** com.springinaction.service.Performance.perform(..))")    public void takeSeats(){        System.out.println("找座位");    }    @AfterReturning("execution(** com.springinaction.service.Performance.perform(..))")    public void applause(){        System.out.println("再来一个");    }    @AfterThrowing("execution(** com.springinaction.service.Performance.perform(..))")    public void demandRefund(){        System.out.println("垃圾,炒鸡垃圾");    }    @Around("execution(** com.springinaction.service.Performance.perform(..))")    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{          System.out.println("进入环绕通知");          Object object = pjp.proceed();//执行该方法          System.out.println("退出环绕通知");          return object;      }}

不嫌麻烦,这也是可以的。下面是切点表达式的解释(照着springinaction上绘制的)
表达式介绍
只要实现Performanceperform的方法,就会依次执行@Before,@AfterReturning,@AfterThrowing。当然使用@Around方法可以代替以上三个注解。
下面看一下目录结构(先不用管红线划去的地方)
这里写图片描述

编写测试类

package com.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.springinaction.service.Actor;public class ShowTest {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-annotation.xml");        Actor actor = (Actor)context.getBean("actor");        actor.perform();    }}

运行结果为:

进入环绕通知找座位表演中...退出环绕通知再来一个

XML配置

使用xml,你就要注册每一个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: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-4.1.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-context-4.1.xsd">    <bean id="oldClown" class="com.springinaction.service.OldClown" />    <bean id="audienceXml" class="com.springinaction.aop.AudienceXml" />    <aop:aspectj-autoproxy proxy-target-class="true" />    <aop:config>        <aop:aspect id="aspect" ref="audienceXml">            <aop:pointcut                expression="execution(** com.springinaction.service.Performance.perform(..))"                id="performance" />            <aop:before method="takeSeats" pointcut-ref="performance" />            <aop:after-returning method="applause"                pointcut-ref="performance" />            <aop:after-throwing method="demandRefund"                pointcut-ref="performance" />            <aop:around method="doBasicProfiling" pointcut-ref="performance" />        </aop:aspect>    </aop:config></beans>

上面没有注册spring扫描的功能,所有的bean都要自己去声明。aspect的配置要和下面的AudienceXml 一一对应。

编写OldClown实现接口

同样实现Performance 接口

package com.springinaction.service;public class OldClown implements Performance {    @Override    public void perform() {        System.out.println("老小丑演技更加佳");    }}

编写一个切面

这里的切面没有任何注解,所有的功能都在xml里配置了

package com.springinaction.aop;import org.aspectj.lang.ProceedingJoinPoint;public class AudienceXml {    public void performance(){}    public void takeSeats(){        System.out.println("找座位");    }    public void applause(){        System.out.println("再来一个");    }    public void demandRefund(){        System.out.println("垃圾,炒鸡垃圾");    }    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{          System.out.println("进入环绕通知");          Object object = pjp.proceed();//执行该方法          System.out.println("退出环绕通知");          return object;      } }

编写测试类

package com.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.springinaction.service.OldClown;public class ShowTestXml {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-xml.xml");        OldClown oldClown = (OldClown)context.getBean("oldClown");// TODO        oldClown.perform();    }}

运行的结果为:

找座位进入环绕通知老小丑演技更加佳退出环绕通知再来一个

到此spring切点的注解与xml配置已经都已经完成,这些是springaop的最基本实现方式,具体的还要看所属的项目结构。

下一篇将会介绍springaop处理通知中的参数,还有本节所有的代码下载地址

0 0
原创粉丝点击