首页 > 其他分享 >spring学习日记-day6-AOP

spring学习日记-day6-AOP

时间:2024-09-02 20:54:24浏览次数:10  
标签:day6 spring void 目标 AOP 执行 方法 public

一、学习目标

        面向切面的编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象的编程(OOP)。OOP中模块化的关键单位是类,而AOP中模块化的单位是切面。切面使跨越多种类型和对象的关注点(如事务管理)模块化。

        spring的关键组件之一是AOP框架。虽然Spring IoC容器并不依赖于AOP(意味着如果你不想使用AOP,就不需要使用),但AOP补充了Spring IoC,提供了一个非常有能力的中间件解决方案。  

        AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它旨在提高模块化程度。在AOP中,程序被划分为不同的关注点(或称为切面),这些关注点可以独立地开发、修改和重用。AOP主要用于处理横切关注点(cross-cutting concerns),这些关注点通常跨越多个类或方法,如日志记录、事务管理、安全控制、性能监控等。

二、AOP

        AOP的核心概念

  1. 切面(Aspect):切面是跨多个类和方法的横切关注点的模块化,如事务管理。切面可以定义切入点、通知(增强)等。

  2. 连接点(Joinpoint):连接点是程序执行中的一个点,如方法的执行或异常的处理。在Spring AOP中,连接点通常是方法的执行点。

  3. 切入点(Pointcut):切入点是一组连接点的集合,这些连接点通常与特定的类或方法相关。切入点定义了哪些连接点将被增强(即应用通知)。

  4. 通知(Advice):通知是切面在特定连接点执行的动作。通知有多种类型,包括前置通知(在方法执行前执行)、后置通知(在方法执行后执行)、环绕通知(在方法执行前后执行,并可以决定方法是否继续执行)、异常通知(在方法抛出异常时执行)和最终通知(无论方法是否成功执行,都会执行)。

  5. 目标对象(Target):目标对象是被一个或多个切面增强的对象。

  6. 代理(Proxy):代理是由AOP框架创建的对象,用于实现切面功能的织入。代理对象在目标对象的基础上增加了额外的功能。

  7. 织入(Weaving):织入是将切面应用到目标对象并创建代理对象的过程。织入可以在编译时、类加载时或运行时进行。

三、三种实现方式

1.搭建测试环境

项目结构:

导入依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.2</version>
        </dependency>
        <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

接口类

public interface  blogService {
    public void addBlog();
    public void deletBlog();
    public void  updateBlog();
    public void  query();
}

接口实现类

public class blogServiceImpl implements blogService{
    public void addBlog() {
        System.out.println("增加了一篇博客");
    }

    public void deletBlog() {

    }

    public void updateBlog() {

    }

    public void query() {

    }
}

xml文件中注册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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注册bean-->
    <bean id="blog" class="com.lzh.service.blogServiceImpl"></bean>
    
</beans>

测试

public class myTest {
    @Test
    public void  test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        blogService blog = (blogService) context.getBean("blog");
        blog.addBlog();
    }
}

2.springAPI实现

        通过Spring的AOP功能,实现了在不修改blogServiceImpl类代码的情况下,为其所有方法执行前后添加额外的逻辑。这是通过定义切入点来指定哪些方法会被拦截,并通过定义顾问来指定在这些方法执行前后执行哪些逻辑(即BeforeAfter类中的方法)来实现的。

/**  
 * 实现了Spring AOP的AfterReturningAdvice接口的类,用于在目标方法正常执行完成后执行一些逻辑。  
 * 这个类将作为AOP通知(Advice)使用,在Spring配置中需要被注册为一个Bean,并与切点(Pointcut)关联。  
 */  
public class After implements AfterReturningAdvice {  
  
    /**  
     * 当目标方法正常执行完成后,此方法将被调用。  
     *   
     * @param returnValue 目标方法的返回值。如果目标方法没有返回值(即void类型),则此参数为null。  
     * @param method 被调用的目标方法对象,包含了方法的所有信息(如名称、参数类型等)。  
     * @param args 传递给目标方法的参数数组。如果目标方法没有参数,则此数组为空。  
     * @param target 目标对象实例,即被代理的对象。  
     * @throws Throwable 如果在通知执行过程中发生异常,则此异常将被抛出。  
     *                   注意:如果此通知中抛出了异常,它可能会阻止后续通知(如果有的话)的执行,  
     *                   并且可能会影响到目标方法的返回值(如果目标方法返回void,则不会有影响)。  
     */  
    @Override  
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {  
        // 输出目标方法执行后的相关信息  
        System.out.println("执行了" + target.getClass().getName() // 目标对象的类名  
                + "的" + method.getName() + "方法," // 目标方法的名称  
                + "返回值:" + returnValue); // 目标方法的返回值  
    }  
}

/**  
 * Before类实现了Spring AOP的MethodBeforeAdvice接口,  
 * 用于在目标方法执行之前执行一些前置逻辑。  
 *   
 * 这个类可以被Spring容器管理,并通过AOP配置应用到指定的目标方法上,  
 * 以实现无侵入式的日志记录、安全检查、性能监控等功能。  
 */  
public class Before implements MethodBeforeAdvice {  
  
    /**  
     * before方法会在目标方法执行之前被调用。  
     *   
     * @param method  被调用的目标方法的Method对象,包含方法名、参数类型等信息。  
     * @param args    目标方法执行时传入的参数数组,如果方法没有参数,则为空数组。  
     * @param target  目标对象,即被代理的对象,实际执行方法的那个对象。  
     * @throws Throwable 如果前置逻辑执行中抛出异常,则此异常会被传递给调用者,  
     *                   可能导致目标方法不会被执行。  
     *   
     * 此方法的主要用途是执行一些前置逻辑,如日志记录、权限检查等,  
     * 而不改变目标方法的参数或返回值。  
     */  
    @Override  
    public void before(Method method, Object[] args, Object target) throws Throwable {  
        // 输出目标对象的类名、被调用的方法名以及一个简单的执行通知  
        System.out.println(target.getClass().getName() + "的" + method.getName() + "方法被执行了");  
    }  
}

    <!--注册bean-->
    <bean id="blog" class="com.lzh.service.blogServiceImpl"></bean>
    <bean id="before" class="com.lzh.service.Before"></bean>
    <bean id="after" class="com.lzh.service.After"></bean>
    <!--aop的配置-->
    <!--切入点  expression:表达式匹配要执行的方法-->
     <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.lzh.service.blogServiceImpl.*(..))"/>
        <aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
    </aop:config>

3.自定义类实现

public class MyPointcut {
    public void before(){
        System.out.println("--before--");
    }
    public void after(){
        System.out.println("--after--");
    }
}

修改xml文件:

    <!--注册bean-->
    <bean id="blog" class="com.lzh.service.blogServiceImpl"></bean>
    <bean id="before" class="com.lzh.service.Before"></bean>
    <bean id="after" class="com.lzh.service.After"></bean>
    <bean id="second" class="com.lzh.config.MyPointcut"></bean>
    <!--aop的配置-->
    <!--aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.lzh.service.blogServiceImpl.*(..))"/>
        <aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
    </aop:config-->
    <!--aop的配置-->
    <aop:config>
        <aop:aspect ref="second">
            <aop:pointcut id="myPonitcut" expression="execution(* com.lzh.service.blogServiceImpl.*(..))"/>
            <aop:before pointcut-ref="myPonitcut" method="before"/>
            <aop:after pointcut-ref="myPonitcut" method="after"/>
        </aop:aspect>
    </aop:config>

测试结果:

4.注解实现

// 使用@Aspect注解定义一个切面类,用于在指定的方法执行前后或周围进行增强处理  
@Aspect  
public class AnnotationPointcut {  
  
    // 使用@Before注解定义一个前置增强,该增强会在指定方法执行前执行  
    // "execution(* com.lzh.service.blogServiceImpl.*(..))"是切点表达式,表示匹配com.lzh.service.blogServiceImpl包下所有类的所有方法  
    @Before("execution(* com.lzh.service.blogServiceImpl.*(..))")  
    public void before(){  
        System.out.println("---before---"); // 在匹配的方法执行前打印信息  
    }  
  
    // 使用@After注解定义一个后置增强,该增强会在指定方法执行后执行(无论方法是否抛出异常)  
    @After("execution(* com.lzh.service.blogServiceImpl.*(..))")  
    public void after(){  
        System.out.println("---after---"); // 在匹配的方法执行后打印信息  
    }  
  
    // 使用@Around注解定义一个环绕增强,该增强可以在方法执行前后进行自定义处理  
    // 环绕增强需要接收一个ProceedingJoinPoint类型的参数,用于控制目标方法的执行  
    @Around("execution(* com.lzh.service.blogServiceImpl.*(..))")  
    public Object around(ProceedingJoinPoint jp) throws Throwable {  
        System.out.println("环绕前"); // 在目标方法执行前打印信息  
        System.out.println("签名:"+jp.getSignature()); // 打印目标方法的签名信息  
  
        // 通过jp.proceed()执行目标方法,并获取其返回值  
        // 注意:如果目标方法抛出异常,这里也会抛出相同的异常  
        Object proceed = jp.proceed();  
  
        System.out.println("环绕后"); // 在目标方法执行后打印信息  
        System.out.println(proceed); // 打印目标方法的返回值  
  
        // 返回目标方法的执行结果  
        return proceed;  
    }  
}

    <!--注册bean-->
    <bean id="blog" class="com.lzh.service.blogServiceImpl"></bean>
    <bean id="before" class="com.lzh.service.Before"></bean>
    <bean id="after" class="com.lzh.service.After"></bean>
    <bean id="second" class="com.lzh.config.MyPointcut"></bean>
    <!--aop的配置-->
    <!--aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.lzh.service.blogServiceImpl.*(..))"/>
        <aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
    </aop:config-->
    <!--aop的配置-->
    <!--aop:config>
        <aop:aspect ref="second">
            <aop:pointcut id="myPonitcut" expression="execution(* com.lzh.service.blogServiceImpl.*(..))"/>
            <aop:before pointcut-ref="myPonitcut" method="before"/>
            <aop:after pointcut-ref="myPonitcut" method="after"/>
        </aop:aspect>
    </aop:config-->
    <bean id="annotationPointcut" class="com.lzh.config.AnnotationPointcut"/>
    <aop:aspectj-autoproxy/>

标签:day6,spring,void,目标,AOP,执行,方法,public
From: https://blog.csdn.net/2301_79789506/article/details/141336090

相关文章

  • [原创精品]基于Springboot+Vue的新闻门户网站、新闻管理系统、新闻资讯网(仿央视网等)
    项目提供:完整源码+数据库sql文件+数据库表Excel文件1、项目功能描述本项目为双角色,用户和管理员,用户使用前台,管理员使用后台。1.1注册注册功能:填写用户名、密码进行注册。(“我已阅读同意《隐私政策》和《服务条款》”没有做后续,只是单纯有这样一行文字做模拟)1.2登......
  • 深入理解Spring Cloud Consul的KV存储与配置中心功能
    深入理解SpringCloudConsul的KV存储与配置中心功能SpringCloudConsul是SpringCloud生态系统中的一个重要组件,用于微服务注册、发现和配置管理。它基于Consul的功能,提供了一种轻量级的服务注册与发现的解决方案,并且支持键值(KV)存储,这使得它可以作为配置中心来管理......
  • SpringCloud-搭建XXL-JOB任务调度平台
    本教程提供了从XXL-JOB平台介绍到具体搭建流程的详细说明,旨在帮助开发者和系统管理员快速理解和部署XXL-JOB任务调度平台。通过SpringCloud集成XXL-JOB任务调度平台,可以使微服务环境中的任务调度更加灵活和高效。整个过程中,调度中心和执行器的正确配置是关键。此外,通过XXL-JOB提供......
  • 使用Redis调用Lua脚本的方式对SpringBoot接口进行限流
    使用Redis调用Lua脚本的方式对SpringBoot接口进行限流使用Redis调用Lua脚本的方式对SpringBoot接口进行限流前言一、步骤1、自定义限流注解Limit.java,用于标注在需要限流的接口上2、编写限流类型枚举类LimitType.java3、编写限流具体实现类LimitAspect.java,通过AOP方式......
  • 每日一题08:说一下Spring AOP动态代理模式
    回答1:SpringAOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。SpringAOP中的动态代理主要有两种方式,JDK动态代理和CGL......
  • 谈谈springboot中@Conditional相关注解
    @Conditional是一个元注解 @ConditionalOnClass(xx.class)这是用于修饰一个类的注解。它主要是让你的代码具有兼容性,如在多模块下common模块中有一些仅仅是部分其他模块依赖、需要配置的类(例如rabbitMQ配置类,我相信他不应该被全模块需要,但是他放在常用模块中依旧是最合适的)只......
  • Spring扩展点系列-InstantiationAwareBeanPostProcessor
    文章目录简介测试一1、配置文件Bean注册2、单元测试方法3、测试类4、输出结果结论测试二1、测试类2、输出结果结论源码解析postProcessPropertiesCommonAnnotationBeanPostProcessorAnnotationInjectedBeanPostProcessor总结简介spring容器中Bean的生命周期内所......
  • springboot多媒体内容管理系统-计算机毕业设计源码08580
    摘 要随着人类向信息社会的不断迈进,风起云涌的信息时代正掀起一次新的革命,同时计算机网络技术高速发展,网络管理运用也变得越来越广泛。因此,建立一个多媒体内容管理系统(CMS)的设计与优化来管理多媒体内容信息,会使管理工作系统化、规范化,提高管理效率。本课题的研究对象是多媒......
  • springboot中小型酒店管理系统-计算机毕业设计源码02793
    摘要随着互联网和移动技术的快速发展,酒店行业也面临着巨大的变革和机遇。传统的酒店管理方式存在着信息不透明、预订流程繁琐等问题,无法满足现代消费者对便捷、高效、个性化服务的需求。因此,开发中小型酒店管理系统具有重要的意义。本文旨在设计和实现一种功能完善、易用且可......
  • Java服务端服务监控:Prometheus与Spring Boot Actuator的集成
    Java服务端服务监控:Prometheus与SpringBootActuator的集成大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代Java服务端开发中,服务监控是确保系统稳定性和性能的关键。Prometheus是一个开源的系统监控和警报工具,而SpringBootActuator提供了生......