实例说明spring实现aop的2种方式(注解和xml配置)

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

本文说到sPRing的配置,常见的有两种:注解方式和xml文件配置方式。(直接上实例,所以细节方面不会提及)

本人用的是maven项目,下面附上maven pom文件的依赖jar:

1<dependencies>2<dependency>3<groupId>junit</groupId>4<artifactId>junit</artifactId>5<version>3.8.1</version>6<scope>test</scope>7</dependency>8<dependency>9<groupId>org.springframework</groupId>10<artifactId>spring-context</artifactId>11<version>4.2.1.RELEASE</version>12</dependency>13<dependency>14<groupId>commons-logging</groupId>15<artifactId>commons-logging</artifactId>16<version>1.2</version>17</dependency>18<dependency>19<groupId>org.jdom</groupId>20<artifactId>jdom</artifactId>21<version>1.1.3</version>22</dependency>23<dependency>24<groupId>cglib</groupId>25<artifactId>cglib-nodep</artifactId>26<version>2.1_3</version>27</dependency>28<dependency>29<groupId>org.aspectj</groupId>30<artifactId>aspectjrt</artifactId>31<version>1.6.11</version>32</dependency>33<dependency>34<groupId>org.aspectj</groupId>35<artifactId>aspectjweaver</artifactId>36<version>1.6.11</version>37</dependency>38</dependencies>

maven pom.xml

下面图文说明我们src下的包结构:

上图所示 就是我们的包文件以及需要的几个类:

首先, 建立model类UserManager,代码如下:

1packagecom.wangku.spring.model;23publicclassUserManager {45privateintid;6privateString name;7privateString passWord;89publicintgetId() {10returnid;11}12publicvoidsetId(intid) {13this.id =id;14}15publicString getName() {16returnname;17}18publicvoidsetName(String name) {19this.name =name;20}21publicString getPassword() {22returnpassword;23}24publicvoidsetPassword(String password) {25this.password =password;26}2728}

UserManagerr

然后, 建立一个测试service接口IUserManagerService类,代码如下:

1packagecom.wangku.spring.service;23importcom.wangku.spring.model.UserManager;45publicinterfaceIUserManagerService {67publicvoidaddUser(String userName, String password);89publicvoidupdateUser(intuserId, String userName, String password);1011publicvoiddeleteUser(intuserId);1213publicUserManager findUser(intuserId);14}

IUserManagerService

接着写一个实现类UserManagerServiceImpl并实现上面的接口,代码如下:

1packagecom.wangku.spring.service.impl;23importorg.springframework.stereotype.Service;45importcom.wangku.spring.model.UserManager;6importcom.wangku.spring.service.IUserManagerService;78@Service("manager")9publicclassUserManagerServiceImplimplementsIUserManagerService{1011publicvoidaddUser(String userName, String password) {12System.out.println("--------------UserManager addUser-------------");13}1415publicvoidupdateUser(intuserId, String userName, String password) {16System.out.println("--------------UserManager updateUser-------------");17}1819publicvoiddeleteUser(intuserId) {20System.out.println("--------------UserManger deleteUser-------------");21}2223publicUserManager findUser(intuserId) {24UserManager userManager =newUserManager();25System.out.println("--------------UserManager findUser-------------");26returnuserManager;27}28}

UserManagerServiceImpl

此时在spring的配置文件添加UserManagerServiceImpl的bean,代码如下:

1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="http://www.springframework.org/schema/beans"3xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"4xmlns:context="http://www.springframework.org/schema/context"5xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"6xmlns:jpa="http://www.springframework.org/schema/data/jpa"7xsi:schemaLocation="8http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.1.xsd9http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.1.xsd10http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.1.xsd11http://www.springframework.org/schema/jdbchttp://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd12http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.1.xsd13http://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa.xsd">1415<bean id="userManager"class="com.wangku.spring.service.impl.UserManagerServiceImpl" />1617</beans>

applicationContext.xml

配置好bean之后,我们建立一个测试类写测试用例测试我们的model,代码如下:

1importorg.junit.Test;2importorg.springframework.context.ApplicationContext;3importorg.springframework.context.support.ClassPathXmlApplicationContext;45importcom.wangku.spring.service.IUserManagerService;67publicclassTestUserManager {89@Test10@SuppressWarnings("resource")11publicvoidtestUserManager() {1213ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");14IUserManagerService userBean = (IUserManagerService) ctx.getBean("userManager");15userBean.addUser("zhaolibin", "buzhidao");16}17}

TestUserManager

Junit运行实例后,打印如下结果:

--------------UserManager addUser-------------

一: XML配置AOP:

现在我们首先用xml文件配置方式来实现aop,spring aop中有好多切面、通知之类的理论知识在此不多说了,直接来实例,写一个切面类,在类中写上常见几个通知的方法,代码如下:

1packagecom.wangku.spring.util;23importorg.aspectj.lang.ProceedingJoinPoint;45publicclassInterceptorAop {67publicvoiddoBefore() {8System.out.println("========执行前置通知==========");9}1011publicvoiddoAferReturning() {12System.out.println("=========执行后置通知================");13}1415publicvoiddoAfter() {16System.out.println("========执行最终通知==========");17}1819publicvoiddoAferThrowing() {20System.out.println("=============执行意外通知================");21}2223publicObject doAround(ProceedingJoinPoint pjp)throwsThrowable {2425System.out.println("=========进入判断方法===========");26Object result =pjp.proceed();27System.out.println("==========进入退出方法==========");28returnresult;29}30}

InterceptorAop

然后我们需要在spring的xml文件里配置切点类以及对应的方法,代码如下:

<bean id="aspetBean" class="com.wangku.spring.util.InterceptorAop"/>

<aop:config>

<aop:aspect id="aspet" ref="aspetBean">

<aop:pointcut expression="execution (* com.wangku.spring.service.impl..*.*(..))" id="cut"/>

<aop:before pointcut-ref="cut" method="doBefore"/>

<aop:after-returning pointcut-ref="cut" method="doAferReturning"/>

<aop:after pointcut-ref="cut" method="doAfter"/>

<aop:after-throwing pointcut-ref="cut" method="doAferThrowing"/>

<aop:around pointcut-ref="cut" method="doAround"/>

</aop:aspect>

</aop:config>

在此大概说下上面的切入点表达式:

1execution (* com.wangku.spring.service.impl..*.*(..))2execution : 表示执行3第一个*号 : 表示返回值类型, *可以是任意类型4com.wangku.spring.service.impl :代表扫描的包5..:代表其底下的子包也进行拦截6第二个*号 : 代表对哪个类进行拦截,*代表所有类7第三个*号 : 代表方法 *代表任意方法8(..) : 代表方法的参数有无都可以

此时配置已经起作用了,再次运行测试用例可以发下打印如下结果:

========执行前置通知==========

=========进入判断方法===========

--------------UserManager addUser-------------

==========进入退出方法==========

========执行最终通知==========

=========执行后置通知================

细心的同学可以观察下不同的通知执行的时机。

上面就是xml配置的情况,但通常情况下 xml配置略显繁琐,所以我们来看看注解配置如何进行。

二:注解配置AOP

使用注解使一切都变得简单,首先spring配置文件中加入注解和支持注释的配置,代码如下:

<aop:aspectj-autoproxy/>

<context:annotation-config />

<context:component-scan base-package="com.wangku.spring" />

最下面的一行配置是指我们要扫描的包。此时有人可能注意到了我们之前写的serviceImpl中的一句注解:@Service("manager")

此时我们的xml是支持扫描的,所以我们在spring配置文件中去掉bean的配置,值保持上面的这几行配置文件,然后在Junit里执行下面代码:

@Test

@SuppressWarnings("resource")publicvoidtestUserManager() {

ApplicationContext ctx=newClassPathXmlApplicationContext("applicationContext.xml");

IUserManagerService userBean= (IUserManagerService) ctx.getBean("manager");

userBean.addUser("zhaolibin", "buzhidao");

}

打印出了我们意料中的结果,然后我们开始用注解的方式配置aop切面类,具体代码如下:

1packagecom.wangku.spring.util;23importorg.aspectj.lang.annotation.After;4importorg.aspectj.lang.annotation.Aspect;5importorg.aspectj.lang.annotation.Before;6importorg.aspectj.lang.annotation.Pointcut;78@Aspect9publicclassInterceptor {1011@Pointcut("execution (* com.wangku.spring.service.impl..*.*(..))")12privatevoidanyMethod() {13System.out.println("============进入anyMethod方法==============");14}1516@Pointcut("execution (* com.wangku.spring.service.test..*.*(..))")17privatevoidsomeMethod() {18System.out.println("============进入someMethod方法==============");19}2021@Before("anyMethod()")22publicvoiddoBefore() {23System.out.println("==========执行前置通知===============");24}2526@After("someMethod()")27publicvoiddoAfter() {28System.out.println("===========执行最终通知==============");29}30}

Interceptor

因为是切面类,所以使用@Aspect注解此类,然后用@Pointcut来指定切面表达式,此处我定义了2个切面表达式。

在spring配置文件中加入切面类的bean,如下

<bean id="interceptor"class="com.wangku.spring.util.Interceptor"/>

此时再次运行上面的Junit,会发现打印如下结果:

==========执行前置通知===============

--------------UserManager addUser-------------

注解已经执行了。接着在service下面再建立另一个test包,下面新建一个UserTestServiceImpl类进行多切面表达式的测试, 代码如下

1packagecom.wangku.spring.service.test;23importorg.springframework.stereotype.Service;45importcom.wangku.spring.model.UserManager;6importcom.wangku.spring.service.IUserManagerService;78@Service("tester")9publicclassUserTestServiceImplimplementsIUserManagerService{1011publicvoidaddUser(String userName, String password) {12System.out.println("--------------UserTestServiceImpl addUser-------------");13}1415publicvoidupdateUser(intuserId, String userName, String password) {16System.out.println("--------------UserTestServiceImpl updateUser-------------");17}1819publicvoiddeleteUser(intuserId) {20System.out.println("--------------UserTestServiceImpl deleteUser-------------");21}2223publicUserManager findUser(intuserId) {24System.out.println("--------------UserTestServiceImpl findUser-------------");25returnnull;26}27}

UserTestServiceImpl

此时利用execution (* com.wangku.spring.service.test..*.*(..))切面表达式来扫描我们新建的测试类,在Junit测试用例中执行以下代码:

ApplicationContext ctx =newClassPathXmlApplicationContext("applicationContext.xml");

IUserManagerService userBean= (IUserManagerService) ctx.getBean("tester");

userBean.addUser("zhaolibin", "buzhidao");

执行结果如下:

--------------UserTestServiceImpl addUser-------------

===========执行最终通知==============

由此可见,我们可以配置不同的切面表达式针对不同的类进行切面处理,当然通常情况下多用于权限等的控制。

spring aop的xml文件配置还有其他不同的形式,例如通过

<aop:config>

<aop:advisor advice-ref=""/>

</aop:config>

这种形式,不过殊途同归,只要了解其中的原理就好。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航