实例说明Spring实现AOP的2种方式(注解和XML配置)

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

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

package com.spring.model;

public class UserManager {

    private int id;
    private String name;
    private String password;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

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

package com.spring.service.impl;

import org.springframework.stereotype.Service;

import com.spring.model.UserManager;
import com.spring.service.IUserManagerService;

@Service("manager")
public class UserManagerServiceImpl implements IUserManagerService{

    public void addUser(String userName, String password) {
        System.out.println("--------------UserManager addUser-------------");
    }

    public void updateUser(int userId, String userName, String password) {
        System.out.println("--------------UserManager updateUser-------------");
    }

    public void deleteUser(int userId) {
        System.out.println("--------------UserManger deleteUser-------------");
    }

    public UserManager findUser(int userId) {
        UserManager userManager = new UserManager();
        System.out.println("--------------UserManager findUser-------------");
        return userManager;
    }
}
此时在spring的配置文件添加UserManagerServiceImpl的bean,代码如下:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
        
        <bean id="userManager" class="com.spring.service.impl.UserManagerServiceImpl" />
</beans>
配置好bean之后,我们建立一个测试类写测试用例测试我们的model,代码如下:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.service.IUserManagerService;

public class TestUserManager {

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

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

--------------UserManager addUser-------------
一: XML配置AOP:

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

package com.spring.util;
import org.aspectj.lang.ProceedingJoinPoint;
public class InterceptorAop {

    public void doBefore() {
        System.out.println("========执行前置通知==========");
    }
    
    public void doAferReturning() {
        System.out.println("=========执行后置通知================");
    }
    
    public void doAfter() {
        System.out.println("========执行最终通知==========");
    }
    
    public void doAferThrowing() {
        System.out.println("=============执行意外通知================");
    }
    
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        
        System.out.println("=========进入判断方法===========");
        Object result = pjp.proceed();
        System.out.println("==========进入退出方法==========");
        return result;
    }
}
然后我们需要在spring的xml文件里配置切点类以及对应的方法,代码如下:
<bean id="aspetBean" class="com.spring.util.InterceptorAop"/>
<aop:config>
    <aop:aspect id="aspet" ref="aspetBean">
         <aop:pointcut expression="execution (* com.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.spring.service.impl..*.*(..))
2、execution : 表示执行
3、第一个*号 : 表示返回值类型, *可以是任意类型
4、com.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.spring" />

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

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

 @Test
    @SuppressWarnings("resource")
    public void testUserManager() {
        
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserManagerService userBean = (IUserManagerService) ctx.getBean("manager");
        userBean.addUser("zhaolibin", "buzhidao");
    } 
打印出了我们意料中的结果,然后我们开始用注解的方式配置aop切面类,具体代码如下:

package com.wangku.spring.util;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Interceptor {
    
    @Pointcut("execution (* com.wangku.spring.service.impl..*.*(..))")
    private void anyMethod() {
        System.out.println("============进入anyMethod方法==============");
    }
    
    @Pointcut("execution (* com.wangku.spring.service.test..*.*(..))")
    private void someMethod() {
        System.out.println("============进入someMethod方法==============");
    }
    
    @Before("anyMethod()")
    public void doBefore() {
        System.out.println("==========执行前置通知===============");
    }
    
    @After("someMethod()")
    public void doAfter() {
        System.out.println("===========执行最终通知==============");
    }
}

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

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

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

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

==========执行前置通知===============
--------------UserManager addUser-------------

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

package com.spring.service.test;

import org.springframework.stereotype.Service;

import com.spring.model.UserManager;
import com.spring.service.IUserManagerService;

@Service("tester")
public class UserTestServiceImpl implements IUserManagerService{

    public void addUser(String userName, String password) {
        System.out.println("--------------UserTestServiceImpl addUser-------------");
    }

    public void updateUser(int userId, String userName, String password) {
        System.out.println("--------------UserTestServiceImpl updateUser-------------");
    }

    public void deleteUser(int userId) {
        System.out.println("--------------UserTestServiceImpl deleteUser-------------");
    }

    public UserManager findUser(int userId) {
        System.out.println("--------------UserTestServiceImpl findUser-------------");
        return null;
    }
}

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

    ApplicationContext ctx = new ClassPathXmlApplicationContext("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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值