Aspectj的使用demo

4 篇文章 0 订阅

aop编程就是使用了动态代理,但是spring的aop来做面向切面编程会比较麻烦,Aspectj这个包也提供了类似于spring的aop编程,通过注解来配置以及表达式的配置实现并且可以动态给对象添加方法(但是要做类型转换),用起来十分方便

  • 介绍下下面5个注解:

1.@Before
前置通知,在方法执行前调用

2.@AfterReturning
返回通知,在方法返回结果之后调用

3.@AfterThrowing
异常通知,在方法抛出异常后调用

4.@After
后置通知,在方法执行完成调用

5.@Around
环绕通知,包含上面4种,围绕着方法执行

  • 其他注解:

1.@DeclareParents
用来动态给对象添加属性和方法

2.@Pointcut
定义切入点,用于后面方法表达式的复用

1、2、3、4种通知,调用方法的时候可以自动传入一个JoinPoint 对象,用来获取方法名字或者代理对象或者传入的参数等等,其中第2种AfterReturning可以定义returning = “xxx” 来获取方法调用之后的返回值,第3种AfterThrowing可以定义throwing=”xxx” 来获取抛出的异常对象

5种通知,调用方法适合可以传入一个ProceedingJoinPoint 对象,同上一样可以获取各种信息并且有执行目标对象的方法proceed()

上面的5种的execution表达式都可以配合注解来进行筛选执行方法

execution(* *(..)) && @annotation(myAnnotation)

下面写了个小例子:

首先创建一个目标类:

@Component
public class Mytest01 {
    public String show() {
        System.out.println("show time");
        return "show 执行完成";
    }
}

创建一个类,里面包含第一种到第四种的注解:


@Component
@Aspect
public class Mytest02 {


    @Before("execution(* spring06.Mytest01.*(..))")
    public void before(JoinPoint joinPoint) {
        showJoinPoint(joinPoint);
        System.out.println("@Before 执行");
    }

    @AfterReturning(value = "execution(* spring06.Mytest01.*(..))", returning = "result")
    public void afterReturning(JoinPoint joinPoint, String result) {
        System.out.println("@AfterReturning 执行,返回值为:" + result);
    }

    @AfterThrowing(value = "execution(* spring06.Mytest01.*(..))", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Exception exception) {
        System.out.println("@AfterThrowing 执行,异常为:" + exception.getMessage());
    }

    @After("execution(* spring06.Mytest01.*(..))")
    public void after(JoinPoint joinPoint) {
        System.out.println("@After 执行");
    }

    /**
     * joinPoint 常用获取属性
     *
     * @param joinPoint
     */
    private void showJoinPoint(JoinPoint joinPoint) {
        //获取调用的方法名字
        System.out.println("JoinPoint 常用:" + joinPoint.getSignature().getName());
        //获取目标类
        System.out.println("JoinPoint 常用:" + joinPoint.getTarget());
        //获取代理对象
        System.out.println("JoinPoint 常用:" + joinPoint.getThis());
        //获取参数
        System.out.println("JoinPoint 常用:" + joinPoint.getArgs());
    }

}

创建另一个类,里面只包含第五种的注解,以及DeclareParents和Pointcut注解:

@Component
@Aspect
public class Mytest03 {

    /**
     * 给被切面编程的Mytest01对象添加NewServiceImpl里面的参数和方法
     */
    @DeclareParents(value = "spring06.Mytest01", defaultImpl = NewServiceImpl.class)
    private NewService service;

    /**
     * 这里是定义一个切入点,后面的方法都可以直接引用
     */
    @Pointcut("execution(* spring06.Mytest01.*(..))")
    public void myPoint() {

    }

    @Around("myPoint()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("@Around 开始");
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            System.out.println("@Around 获取出异常:" + throwable.getMessage());
        } finally {
            System.out.println("@Around 执行结束");
        }
        System.out.println("@Around 开始返回结果");
        return result;
    }
}

DeclareParents注解需要用到的接口:

public interface NewService {
    String newShow(String show);
}

DeclareParents注解需要用到的实现类:

public class NewServiceImpl implements NewService {
    public String newShow(String show) {
        System.out.println("这是调用的newShow,value = " + show);
        return show;
    }
}

创建一个main入口:

public static void main(String[] args) {
        AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("application06.xml");
        Mytest01 test = appContext.getBean(Mytest01.class);
        test.show();
        NewService service = (NewService) test;
        service.newShow("new");
        appContext.registerShutdownHook();
    }

xml配置:

<context:component-scan base-package="spring06"/>
<aop:aspectj-autoproxy/>

测试前4中注解,先注释掉Mytest03的Aspect注解,执行main方法,结果如下:

这里写图片描述

测试第5种的环绕注解,注释掉Mytest02的Aspect注解,执行main方法,结果如下:

这里写图片描述

小demo完成,我们可以使用它去做一些日志的处理比如Controller被访问前后都打印日志,就可以用aspectj来完成,可以参考java注解结合aspectj AOP进行日志打印

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot整合AspectJ可以实现面向切面编程,用于在应用中添加横切关注点(Cross-cutting Concerns)。下面是一个简单的示例步骤: 1. 在Spring Boot项目的`pom.xml`文件中添加AspectJ依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 2. 创建一个切面类,该类包含一个或多个切点和通知方法。例如,创建一个名为`LoggingAspect`的类: ```java @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.demo.YourService.*(..))") public void beforeMethodExecution(JoinPoint joinPoint) { // 在方法执行前执行的逻辑 System.out.println("Before method execution: " + joinPoint.getSignature().getName()); } @After("execution(* com.example.demo.YourService.*(..))") public void afterMethodExecution(JoinPoint joinPoint) { // 在方法执行后执行的逻辑 System.out.println("After method execution: " + joinPoint.getSignature().getName()); } } ``` 3. 在切面类中定义通知方法,并使用注解指定在哪些连接点上触发该通知。在上面的示例中,`@Before`和`@After`注解分别表示在目标方法执行前和执行后触发通知。你需要根据自己的需求调整切点表达式。 4. 在启动类上添加`@EnableAspectJAutoProxy`注解,启用AspectJ自动代理。 ```java @SpringBootApplication @EnableAspectJAutoProxy public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } } ``` 5. 运行应用程序,并观察控制台输出。在目标方法执行之前和之后,切面中定义的通知方法将分别被触发。 这样,你就成功地将AspectJ与Spring Boot项目整合起来了。你可以根据具体的需求在切面类中添加更多的通知方法和切点表达式。注意,AspectJ提供了丰富的语法和功能,可以处理更复杂的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值