千家信息网

如何理解spring AOP 框架

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,如何理解spring AOP 框架,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。spring AOP (包含基于注解和配
千家信息网最后更新 2025年02月02日如何理解spring AOP 框架

如何理解spring AOP 框架,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

spring AOP (包含基于注解和配置文件两种方式)

spring AOP?面向切面编程,区别于面向对象编程OOP

AspectJ: 是Java社区里面最完整最流行的AOP框架,下面就用aspectJ来上例子

一.基于注解方式

步骤如下:

  1. 引入jar包(spring的必要jar包 以及aspectj的jar包)

  2. 业务方法HelloworldService (类上加上注解@Component,放入到spring ioc容器中)

  3. 切面LogingAop (类上加上注解@Component使其加入到ioc容器中,还需要注解@Aspect,使其成为一个切面)

  4. spring配置文件applicationContext.xml (扫描包,以及aop生成代理类的配置)

  5. 测试

结构如下:

HelloworldService代码实现:

package com.aop.demo;import org.springframework.stereotype.Component;@Componentpublic class HelloworldService {    public int add(int i, int j){        return i+j;    }}

LogingAop代码实现:

package com.aop.demo;import java.util.Arrays;import java.util.List;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Component@Aspectpublic class LogingAop {    @Pointcut("execution(public int com.aop.demo.HelloworldService.add (int,int))")    public void pointcut(){};        @Before(value="pointcut()")    public void beforeMethod(JoinPoint jointPoint){        String methodName = jointPoint.getSignature().getName();        List args = Arrays.asList(jointPoint.getArgs());        System.out.println("Method("+methodName+") args("+args+") Start");    }}

applicationContext.xml中配置

测试代码如下

package com.aop.demo;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AopTest {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        HelloworldService helloworldService = (HelloworldService) ctx.getBean("helloworldService");        int result = helloworldService.add(1, 2);        System.out.println("Result is "+result);    }}

测试结果如下:

Method(add) args([1, 2]) StartResult is 3

AOP中的概念介绍:

切面:跨越应用程序多个模块的功能,比如打日志,比如参数验证,类似这种被模块化的特殊对象
通知: 上面切面中的方法
切入点:相当于查询条件,在哪些业务方法中需要加入通知,spring自动生成新的代理对象

AspectJ支持5中类型的通知注解:

@Before: 前置通知,在方法执行之前执行
@After: 后置通知,在方法执行之后执行 (不管是否有异常,都会执行)
@AfterRuning: 返回通知,在方法返回结果之后执行 (只在没有异常时候才执行)
@AfterThrowing: 异常通知,在方法抛出异常之后
@Around: 环绕通知,围绕着方法执行

AspectJ的5中注解的代码示例

package com.aop.demo;import java.util.Arrays;import java.util.List;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Component@Aspectpublic class LogingAop {    @Pointcut("execution(public int com.aop.demo.HelloworldService.add (int,int))")    public void pointcut(){};        @Before(value="pointcut()")    public void beforeMethod(JoinPoint jointPoint){        String methodName = jointPoint.getSignature().getName();        List args = Arrays.asList(jointPoint.getArgs());        System.out.println("Method("+methodName+") args("+args+") Start");    }        @After(value="pointcut()")    public void afterMethod(JoinPoint jointPoint){        String methodName = jointPoint.getSignature().getName();        List args = Arrays.asList(jointPoint.getArgs());        System.out.println("Method("+methodName+") args("+args+") After");    }        @AfterReturning(value="pointcut()",returning="result")    public void afterReturingMethod(JoinPoint jointPoint,Object result){        String methodName = jointPoint.getSignature().getName();        List args = Arrays.asList(jointPoint.getArgs());        System.out.println("Method("+methodName+") args("+args+") After Runing + Result:"+result);    }        @AfterThrowing(value="pointcut()",throwing="e")    public void afterThrowingMethod(JoinPoint jointPoint,Exception e){        String methodName = jointPoint.getSignature().getName();        List args = Arrays.asList(jointPoint.getArgs());        System.out.println("Method("+methodName+") args("+args+") After Throw Exception:" +e);    }        @Around(value="pointcut()")    public Object aroundMethod(ProceedingJoinPoint jointPoint){                Object result = null;        String methodName = jointPoint.getSignature().getName();        try {            System.out.println(methodName+"前置通知.....");            result = jointPoint.proceed();            System.out.println("后置通知.....");        } catch (Throwable e) {            System.out.println("异常通知.....");            throw new RuntimeException();        }        System.out.println("返回通知.....");        return result;    }}

注意:@Around环绕通知,必须携带对象ProceedingJoinPoint参数

环绕通知类似于动态代理的全部过程,可以决定是否执行目标方法

切面的优先级

可以在切面上注解@Order,其中值越小,切面的优先级越高

二.基于配置文件方式

步骤如下:

  1. 将上面的三个类移到其他包里面,去掉类以及方法中的所有注解

  2. 定义新的配置文件applicationContext-xml.xml

结构如下:

applicationContext-xml.xml的配置

                                                                

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

0