你的位置:首页 > Java教程

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


  本文说到spring的配置,常见的有两种:注解方式和

本人用的是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.

 

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

 

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

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

 1 package com.wangku.spring.model; 2  3 public class UserManager { 4  5   private int id; 6   private String name; 7   private String password; 8    9   public int getId() {10     return id;11   }12   public void setId(int id) {13     this.id = id;14   }15   public String getName() {16     return name;17   }18   public void setName(String name) {19     this.name = name;20   }21   public String getPassword() {22     return password;23   }24   public void setPassword(String password) {25     this.password = password;26   }27 28 }

UserManagerr

 

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

 1 package com.wangku.spring.service; 2  3 import com.wangku.spring.model.UserManager; 4  5 public interface IUserManagerService { 6  7   public void addUser(String userName, String password); 8    9   public void updateUser(int userId, String userName, String password);10   11   public void deleteUser(int userId);12   13   public UserManager findUser(int userId);14 }

IUserManagerService

 

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

 1 package com.wangku.spring.service.impl; 2  3 import org.springframework.stereotype.Service; 4  5 import com.wangku.spring.model.UserManager; 6 import com.wangku.spring.service.IUserManagerService; 7  8 @Service("manager") 9 public class UserManagerServiceImpl implements IUserManagerService{10 11   public void addUser(String userName, String password) {12     System.out.println("--------------UserManager addUser-------------");13   }14 15   public void updateUser(int userId, String userName, String password) {16     System.out.println("--------------UserManager updateUser-------------");17   }18 19   public void deleteUser(int userId) {20     System.out.println("--------------UserManger deleteUser-------------");21   }22 23   public UserManager findUser(int userId) {24     UserManager userManager = new UserManager();25     System.out.println("--------------UserManager findUser-------------");26     return userManager;27   }28 }

UserManagerServiceImpl

 

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

 1 <? 2 <beans  3    4    5    6    7   xsi:schemaLocation=" 8     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 9     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd10     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd11     http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd12     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd13     http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">14     15     <bean id="userManager" class="com.wangku.spring.service.impl.UserManagerServiceImpl" />16 17 </beans>

applicationContext.

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

 1 import org.junit.Test; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPath 4  5 import com.wangku.spring.service.IUserManagerService; 6  7 public class TestUserManager { 8  9   @Test10   @SuppressWarnings("resource")11   public void testUserManager() {12     13     ApplicationContext ctx = new ClassPath);14     IUserManagerService userBean = (IUserManagerService) ctx.getBean("userManager");15     userBean.addUser("zhaolibin", "buzhidao");16   }17 }

TestUserManager

 

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

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

 

 

一: 

 

现在我们首先用

 1 package com.wangku.spring.util; 2  3 import org.aspectj.lang.ProceedingJoinPoint; 4  5 public class InterceptorAop { 6  7   public void doBefore() { 8     System.out.println("========执行前置通知=========="); 9   }10   11   public void doAferReturning() {12     System.out.println("=========执行后置通知================");13   }14   15   public void doAfter() {16     System.out.println("========执行最终通知==========");17   }18   19   public void doAferThrowing() {20     System.out.println("=============执行意外通知================");21   }22   23   public Object doAround(ProceedingJoinPoint pjp) throws Throwable {24     25     System.out.println("=========进入判断方法===========");26     Object result = pjp.proceed();27     System.out.println("==========进入退出方法==========");28     return result;29   }30 }

InterceptorAop

 

然后我们需要在spring的

		<bean id="aspetBean" /> 				<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> 

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

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

 




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

========执行前置通知===================进入判断方法===========--------------UserManager addUser-------------==========进入退出方法==================执行最终通知===================执行后置通知================

 

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

上面就是

二:注解配置AOP

 

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

        <aop:aspectj-autoproxy/> 
        <context:annotation-config />
        <context:component-scan base-package="com.wangku.spring" />

 

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

此时我们的

  @Test  @SuppressWarnings("resource")  public void testUserManager() {        ApplicationContext ctx = new ClassPath);    IUserManagerService userBean = (IUserManagerService) ctx.getBean("manager");    userBean.addUser("zhaolibin", "buzhidao");  }  

 

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

 1 package com.wangku.spring.util; 2  3 import org.aspectj.lang.annotation.After; 4 import org.aspectj.lang.annotation.Aspect; 5 import org.aspectj.lang.annotation.Before; 6 import org.aspectj.lang.annotation.Pointcut; 7  8 @Aspect 9 public class Interceptor {10   11   @Pointcut("execution (* com.wangku.spring.service.impl..*.*(..))")12   private void anyMethod() {13     System.out.println("============进入anyMethod方法==============");14   }15   16   @Pointcut("execution (* com.wangku.spring.service.test..*.*(..))")17   private void someMethod() {18     System.out.println("============进入someMethod方法==============");19   }20   21   @Before("anyMethod()")22   public void doBefore() {23     System.out.println("==========执行前置通知===============");24   }25   26   @After("someMethod()")27   public void doAfter() {28     System.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类进行多切面表达式的测试, 代码如下

 1 package com.wangku.spring.service.test; 2  3 import org.springframework.stereotype.Service; 4  5 import com.wangku.spring.model.UserManager; 6 import com.wangku.spring.service.IUserManagerService; 7  8 @Service("tester") 9 public class UserTestServiceImpl implements IUserManagerService{10 11   public void addUser(String userName, String password) {12     System.out.println("--------------UserTestServiceImpl addUser-------------");13   }14 15   public void updateUser(int userId, String userName, String password) {16     System.out.println("--------------UserTestServiceImpl updateUser-------------");17   }18 19   public void deleteUser(int userId) {20     System.out.println("--------------UserTestServiceImpl deleteUser-------------");21   }22 23   public UserManager findUser(int userId) {24     System.out.println("--------------UserTestServiceImpl findUser-------------");25     return null;26   }27 }

UserTestServiceImpl

 

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

    ApplicationContext ctx = new ClassPath);    IUserManagerService userBean = (IUserManagerService) ctx.getBean("tester");    userBean.addUser("zhaolibin", "buzhidao");

 

执行结果如下:

--------------UserTestServiceImpl addUser-------------===========执行最终通知==============

 

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

 

spring aop的

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

 

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