spring实战(1)-aop

spring aop即切面编程是spring的一重要功能,主要用于完成系统级别的任务。例如:系统日志的记录,权限管理等。这种编程方式的好处是将我们的业务处理和系统级别的问题隔离开。

spring aop术语

  • 通知advice:定义切面的任务和何时调用该通知。主要有前置通知(@Before)、后置通知(@After)、返回通知(@AfterReturning)、异常通知(@AfterThrowing)、环绕通知(@Around)
  • 连接点JoinPoint:程序执行过程中通知会被执行的点,通常是调用某个方法。
  • 切点Pointcut:可以理解成切点的集合,切点的定义会匹配通知所要织入的一个或多个连接点。通常使用类名和方法名或正则表达式所匹配的类或方法名来指定这些切点。
  • 切面Aspect:切面是通知和切点的结合

定义切点

execution:匹配连接点的执行方法

    @Pointcut("execution(* com.example.service..*.*(..))"):第一个*标识匹配任意返回值的方法,..标识0个以上,第一个..表示当前包及其子包,第二个*标识任意类,第三个*标识任意方法,最后一个..标识任意参数。

within:限定匹配方法的连接点

    @Pointcut("within(com.example.service.*)")表示匹配service包下的任意连接点

this:用来限制AOP代理必须是指定的类型

    @Pointcut("this(com.example.service.UserService)")标识aop只能代理UserService

bean

    @Pointcut("bean(userServiceImpl)")限定bean的id为userServiceImpl

@annotation限定被指定注解修饰的方法

常用execution,其他限定一般很少使用。可以使用and或or来连接多个表达式。

SpringBoot环境下使用AOP

定义切面:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class LogAspect {

    @Pointcut("execution(* com.example.test.aop.LogService.*(..))")
    public void pointCut(){};

    @Around("pointCut()")
    public void aroundPoint(ProceedingJoinPoint joinPoint){

        System.out.println("around aop before...");
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("around aop after...");
    }

    @Before("pointCut()")
    public void beforePoint(){

        System.out.println("before aop ...");

    }

    @After("pointCut()")
    public void afterPoint(){

        System.out.println("after aop before...");

    }

    @AfterReturning(pointcut = "pointCut()",returning = "returnObj")
    public void afterReturningPoint(JoinPoint joinPoint,Object returnObj){

        System.out.println("afterReturn aop" + returnObj);
    }

    @AfterThrowing(pointcut = "pointCut()",throwing = "error")
    public void afterThrowPoint(JoinPoint joinPoint,Throwable error){

        System.out.println("afterThrowing aop " + error);
    }
}

定义service:

import org.springframework.stereotype.Service;

@Service
public class LogService {

    public void insert(){
        System.out.println("start insert data to database...");
    }

    public String update(){
        System.out.println("start to update...");
        return "update success";
    }

    public void query(){
        System.out.println("start to query...");
        throw new RuntimeException("query error");
    }
}

定义测试类:

import com.heyu.test.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class TestService {

    @Autowired
    private LogService logService;

    @Test
    public void testInsert(){
        logService.insert();
    }

    @Test
    public void testUpdate(){
        logService.update();
    }

    @Test
    public void testQuery(){
        logService.query();
    }
}

测试testInsert()输出结果:


可以发现各类通知的执行顺序如下:

around before通知 -> before通知 -> 被拦截方法 -> around after通知 -> after通知 -> afterRetruning通知


如果在spring MVC环境,则先将所有的注解去掉,再在配置文件中增加如下代码:

<!-- 配置需要添加aop的类bean -->
<bean id="logService" class="com.example.test.aop.LogService" />

<!-- 配置切面bean -->
<bean id="logAspect" class="com.example.test.aop.LogAspect" />

<!-- 配置aop -->
<aop:config>
	<!-- 配置切点 -->
	<aop:pointcut id="pointCut" expression="execution(* com.example.test.aop.LogService.*(..))"/>
	
	<!-- 配置切点 -->
	<aop:aspect ref="logAspect" order="1">
	
		<aop:before method="beforePoint" pointcut-ref="pointCut"/>
		
	    <aop:after method="afterPoint" pointcut-ref="pointCut"/>
		
	    <aop:after-throwing method="afterThrowPoint" pointcut-ref="pointCut" throwing="error"/>
		
	    <aop:after-returning method="afterReturningPoint" pointcut-ref="pointCut" returning="returnObj"/>
		
		<aop:around method="aroundPoint" pointcut-ref="pointcut"/>
		
	</aop:aspect>
</aop:config>


注:如果想获取代理方法参数,可观察JoinPoint类中的方法,这里具体就不介绍了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值