springAop实现讲解(看这篇够了)

 更新时间:2024年02月04日 10:43:49   作者:screamn  
AOP面向切面编程是一种编程范式,它通过将通用的横切关注点(如日志、事务、权限控制等)与业务逻辑分离,使得代码更加清晰、简洁、易于维护,这篇文章主要介绍了springAop实现讲解(看这篇够了),需要的朋友可以参考下

依赖准备

  • spring-context: 包含Spring的核心功能和上下文支持。
  • spring-aop: 提供了面向切面编程的支持。

spring-context: 包含Spring的核心功能和上下文支持。spring-aop: 提供了面向切面编程的支持。

什么是代理?

二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

在这里插入图片描述

举例:

杨超越是一个明星,她会唱歌和跳舞,她现在想要举办一场演唱会,那么需要场地的租用和场地搭建这个环境的准备,已经后续的拆除。此时对于这个演唱会核心的内容就是明星杨超越唱歌,跳舞,那么非核心的内容就是场地的搭建,拆除,租用等等,这时候对杨超越来说,我只会唱歌跳舞,这方面的我不会,所以此时就可以让他的经纪人去找负责对应业务的职员搭建和准备演唱会。那么这个经纪人就属于代理。核心业务是跳舞唱歌,非核心业务就是演唱会的相关筹办。 当我们需要对核心代码增加非核心业务的逻辑时可以采用代理的技术。

代理分类

静态代理

静态代理是在编译时期就已经确定的代理方式,在静态代理中,需要手动创建一个代理类,该代理类与被代理类实现相同的接口,并持有一个对被代理对象的引用。通过在代理类中调用被代理对象的方法前后加入自定义的逻辑,实现对目标对象方法的增强或控制。

动态代理

动态代理是在运行时期根据被代理对象生成代理类的方式。在动态代理中,不需要手动创建代理类,而是通过使用Java的反射机制,在运行时动态地创建代理类和代理对象。动态代理可以代理任何实现了接口的类,它通过一组接口来描述被代理类的行为,并提供了一个InvocationHandler接口的实现类来处理代理对象的所有方法调用。在方法被调用时,代理对象会将方法的调用转发给InvocationHandler的invoke()方法,并可以在此方法中添加额外的逻辑。

实现方式(动态代理)

  • JDK动态代理:JDK原生的实现方式,需要被代理的目标类必须实现接口!他会根据目标类的接口动态生成一个代理对象!代理对象和目标对象有相同的接口!
  • cglib:通过继承被代理的目标类实现代理,所以不需要目标类实现接口!

AOP 面向切面编程

它允许开发人员分离横切关注点(cross-cutting concerns)和核心业务逻辑。横切关注点是那些存在于应用程序中多个模块中的功能,例如日志记录、性能统计、安全性和事务管理等。通过 AOP,这些横切关注点可以被模块化地定义,并且可以被动态地应用到整个应用程序中。也就是说将核心代码和非核心代码分割开。

使用场景

  • AOP(面向切面编程)是一种编程范式,它通过将通用的横切关注点(如日志、事务、权限控制等)与业务逻辑分离,使得代码更加清晰、简洁、易于维护。AOP可以应用于各种场景,以下是一些常见的AOP应用场景:
  • 日志记录:在系统中记录日志是非常重要的,可以使用AOP来实现日志记录的功能,可以在方法执行前、执行后或异常抛出时记录日志。
  • 事务处理:在数据库操作中使用事务可以保证数据的一致性,可以使用AOP来实现事务处理的功能,可以在方法开始前开启事务,在方法执行完毕后提交或回滚事务。
  • 安全控制:在系统中包含某些需要安全控制的操作,如登录、修改密码、授权等,可以使用AOP来实现安全控制的功能。可以在方法执行前进行权限判断,如果用户没有权限,则抛出异常或转向到错误页面,以防止未经授权的访问。
  • 性能监控:在系统运行过程中,有时需要对某些方法的性能进行监控,以找到系统的瓶颈并进行优化。可以使用AOP来实现性能监控的功能,可以在方法执行前记录时间戳,在方法执行完毕后计算方法执行时间并输出到日志中。
  • 异常处理:系统中可能出现各种异常情况,如空指针异常、数据库连接异常等,可以使用AOP来实现异常处理的功能,在方法执行过程中,如果出现异常,则进行异常处理(如记录日志、发送邮件等)。
  • 缓存控制:在系统中有些数据可以缓存起来以提高访问速度,可以使用AOP来实现缓存控制的功能,可以在方法执行前查询缓存中是否有数据,如果有则返回,否则执行方法并将方法返回值存入缓存中。
  • 动态代理:AOP的实现方式之一是通过动态代理,可以代理某个类的所有方法,用于实现各种功能。

Aop名词介绍

  • 切面(Aspect):横跨多个对象的关注点,如日志记录、安全控制等。切面由切点和通知组成。
  • 连接点(Join Point):程序执行过程中能够插入切面的点,如方法调用、异常处理等。
  • 切点(Pointcut):对连接点进行拦截的定义,如拦截某个包下的所有方法调用。
  • 通知(Advice):切面在连接点处执行的操作,如在方法执行前后添加日志记录、在方法执行发生异常时处理异常等。
  • 织入(Weaving):将切面应用到目标对象并创建新的代理对象的过程。
  • 目标对象(Target Object):被切面织入的对象。
  • 引入(Introduction):在不修改目标对象代码的情况下,为目标对象添加新的方法或属性。
  • AOP代理(AOP Proxy):AOP框架创建的代理对象,用于实现AOP功能。

SpringAop实现(注解的方式)

接口内容:

package com.ssmLearn;
/**
 *       + - * / 运算的标准接口!
 */
public interface Calculator {
    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
}

实现类

package com.ssmLearn;
import org.springframework.stereotype.Component;
/**
 * 实现计算接口,单纯添加 + - * / 实现! 掺杂其他功能!
 */
//最后必须放到ioc
@Component
public class CalculatorPureImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }
    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }
    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }
    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }
}

需要实现的内容

  • 在加减乘除方法中加入日志输出
  • 加入异常方法

实现代码

package com.ssmLearn.Aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//使用注解配置插入的代理目标
@Aspect
@Component
public class AchiveAop {
    @Before("execution(* com.ssmLearn.CalculatorPureImpl.*(..))")
    public void start(){
        System.out.println("这是初始化方法");
    }
    @After("execution(* com.ssmLearn.CalculatorPureImpl.*(..)))")
    public void end(){
        System.out.println("这是结束方法");
    }
    @AfterThrowing(value = "execution(public int com.ssmLearn.CalculatorPureImpl.*(..))")
    public void catchExection(){
        System.out.println("出现异常");
    }
}

代码编写

  • 注解 Aspect 指示一个类是一个切面,告诉aop框架在这个位置执行切入
  • 注解Component用于将这个类放到ioc容器中
  • 编写具体方法逻辑,填写对应的注解内容 ,将切面表达式写入

配置类

package com.ssmLearn.config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = "com.ssmLearn")
//这个是配置的 aspect代理启动入口
@EnableAspectJAutoProxy
public class javaConfig{
}

代码实现

  • Configuration标识配置类
  • ComponentScan扫描包的注解并将它们注册为 Bean。
  • EnableAspectJAutoProxy这个注解开启了 AspectJ 的自动代理功能。

测试类的书写

import com.ssmLearn.Calculator;
import com.ssmLearn.config.javaConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
//@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
@SpringJUnitConfig(value = {javaConfig.class})
class AopTest {
    @Autowired
    private Calculator calculator;
    @Test
    public void testCalculator(){
        int res = calculator.add(1,0);
        System.out.println("res = " + res);
    }
    @Test
    public void test(){
//        使用配置类 就可以直接使用这个ioc容器 直接使用后AnnotationConfigApplicationContext
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(javaConfig.class);
        Calculator bean = applicationContext.getBean(Calculator.class);
        int res = bean.add(1,2);
        System.out.println("res = " + res);
    }
}

代码实现

  • 使用springJunitConfig框架进行测试,填写对应的配置类文件,使用Autowired注解实例化接口。然后使用对象执行相应的方法
  • 使用AnnotationConfigApplicationContext根绝配置类创建,然后获去对象进行调用

到此这篇关于springAop讲解的文章就介绍到这了,更多相关springAop讲解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringMVC访问controller报错404的解决办法(总结超详细)

    SpringMVC访问controller报错404的解决办法(总结超详细)

    纯注解配置SpringMVC程序,使用tomcat8.5.95版本启动,能启动成功并且访问index.jsp页面,但是访问/save时出现404无法访问,本文给大家介绍了SpringMVC访问controller报错404的解决办法,文章总结的非常详细,需要的朋友可以参考下
    2024-05-05
  • JAVA中的Token 基于Token的身份验证实例

    JAVA中的Token 基于Token的身份验证实例

    这篇文章主要介绍了JAVA中的Token 基于Token的身份验证实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Mybatis中的@Select、foreach用法

    Mybatis中的@Select、foreach用法

    这篇文章主要介绍了Mybatis中的@Select、foreach用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Spring Security用户定义 

    Spring Security用户定义 

    这篇文章主要介绍了Spring Security用户定义,大家都知道 Spring Security的用户定义有很多方式,其实主要有两种,基于内存的和基于数据库的,下面我给大家简单介绍一下这两种方式,需要的朋友可以参考下
    2022-02-02
  • IDEA版使用Java操作Redis数据库的方法

    IDEA版使用Java操作Redis数据库的方法

    这篇文章主要介绍了IDEA版使用Java操作Redis数据库的方法,首先需要下载jedis.jar包,然后再工程中设置具体操作步骤跟随小编一起学习下吧
    2021-08-08
  • java关于Date日期类型的大小比较

    java关于Date日期类型的大小比较

    这篇文章主要介绍了java关于Date日期类型的大小比较,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • IDEA中 Getter、Setter 注解不起作用的问题如何解决

    IDEA中 Getter、Setter 注解不起作用的问题如何解决

    这篇文章主要介绍了IDEA中 Getter、Setter 注解不起作用的问题如何解决,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java实现简单计算器功能

    java实现简单计算器功能

    这篇文章主要为大家详细介绍了java实现简单计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • JavaSE一维数组和二维数组用法详解

    JavaSE一维数组和二维数组用法详解

    数组存储同一种数据类型多个元素的集合,既可以存储基本数据类型,也可以存储引用数据类型,这篇文章主要给大家介绍了关于JavaSE一维数组和二维数组用法的相关资料,需要的朋友可以参考下
    2024-04-04
  • ShardingSphere结合MySQL实现分库分表的项目实践

    ShardingSphere结合MySQL实现分库分表的项目实践

    在实际开发中,如果表的数据过大我们需要把一张表拆分成多张表,本文主要介绍了使用ShardingSphere实现MySQL分库分表,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03

最新评论