首页 > 编程语言 >spring之AOP(面向切面编程)

spring之AOP(面向切面编程)

时间:2024-05-13 15:08:10浏览次数:15  
标签:JDK spring void 代理 切面 CGLIB AOP 动态 public

  1. 什么是AOP?

    AOP(Aspect Oriented Programming)意为:面向切面编程,体现了横切的思想,意思是在添加某项功能的时候,是以切面插入的方式实现的,对原有的代码不会产生改变。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

  2. AOP在spring中的作用:在不改变原有代码的情况下,去增加新的功能。

    • 横切关注点:跨越应用程序多个模块的方法或功能。即与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等 …
    • 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。
    • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
    • 目标(Target):被通知对象。
    • 代理(Proxy):向目标对象应用通知之后创建的对象。
    • 切入点(PointCut):切面通知 执行的 “地点”的定义。
    • 连接点(JointPoint):与切入点匹配的执行点。

    SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

  3. aop的实现

    • 需要导入相应的包
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>xxx</version>
    </dependency>
    
    • 第一种实现方式:通过spring API 编写业务接口实现类
    //业务接口
    public interface UserService {
        void add();
    }
    //业务实现类
    public class UserServiceImpl implements UserService {
        @Override
        public void add() {
            System.out.println("执行了add方法");
        }
    }
    
    • 编写增强类:前置和后置
    public class Log implements MethodBeforeAdvice {
        /**
         * target:目标对象
         * args:参数
         * method:目标对象的方法
         */
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+"执行了"+method.getName()+"方法");
        }
    }
    public class AfterLog implements AfterReturningAdvice {
        /**
         * returnValue:返回值
         */
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
            System.out.println("执行了"+method.getName()+"方法,返回结果"+returnValue);
        }
    }
    
    • 编写配置文件,要导入aop的约束
    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--注册bean-->
        <bean id="userService" class="com.test.service.UserServiceImpl"/>
        <bean id="log" class="com.test.log.Log"/>
        <bean id="afterLog" class="com.test.log.AfterLog"/>
        <!--方式一:使用原生Spring API接口 -->
        <!--配置aop:需要导入aop的约束-->
            <aop:config>
            <!--切入点:expression:表达式,execution(要执行的位置! * * * * *) -->
            <aop:pointcut id="pointcut" expression="execution(* com.test.service.UserServiceImpl.*(..))"/>
            <!--执行环绕增加!-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
            </aop:config>
    </beans>
    
    • 测试
    @Test
    public void test1(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
    
    • 第二种方式:自定义类实现AOP
    public class SelfPointcut {
        public void before() {
            System.out.println("使用前");
        }
        public void after() {
            System.out.println("使用后");
        }
    }
    
    • 编写配置类
    <beans>
    <!--方式二:自定义类-->
            <bean id="selfPointcut" class="com.test.self.SelfPointcut"/>
            <aop:config>
            <!--自定义切面, ref 要引用的类-->
            <aop:aspect ref="selfPointcut">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.test.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
            </aop:aspect>
            </aop:config>
    </beans>
    
    • 使用注解的方式:编写使用注解的实现类
    @Aspect// 标注此类是一个切面
    public class AnnotationPointCut {
        @Before("execution(* com.test.service.UserServiceImpl.*(..))")
        public void before(){
            System.out.println("方法执行前");
        }
        @After("execution(* com.test.service.UserServiceImpl.*(..))")
        public void after(){
            System.out.println("方法执行后");
        }
    }
    
    • 编写配置
    <!--方式三-->
    <bean id="annotationPointCut" class="com.test.self.AnnotationPointCut"/>
    <!--开启注解支持!   JDK(默认 proxy-target-class="false")   cglib(proxy-target-class="true")-->
    <aop:aspectj-autoproxy/>
    
  4. spring aop JDK动态代理和cglib动态代理的区别

    • Spring AOP 支持两种类型的动态代理:JDK 动态代理和 CGLIB 动态代理。它们之间有以下区别:

    • 基于类型:JDK 动态代理是基于接口的代理,而 CGLIB 动态代理是基于类的代理。

    • 代理对象创建:JDK 动态代理通过 Java 自带的 java.lang.reflect.Proxy 创建代理对象,该对象必须实现一个或多个接口。CGLIB 动态代理通过字节码生成技术创建代理对象,无需目标类实现接口,直接继承目标类。

    • 性能:JDK 动态代理在运行时需要使用反射,导致较低的性能。CGLIB 动态代理通过生成字节码,避免了反射,因此通常比 JDK 动态代理速度更快。

    • 对象类型:JDK 动态代理只能代理具有接口的目标对象,不适用于没有接口的类。CGLIB 动态代理可以代理任何类,包括没有实现接口的类。

    • 继承:JDK 动态代理只能代理目标对象的接口方法,不能代理其父类中的方法。CGLIB 动态代理可以代理目标类及其父类中的方法。

    • 综上所述,选择使用 JDK 动态代理还是 CGLIB 动态代理取决于具体的需求和场景。如果目标对象实现了接口并且对性能要求较高,可以选择 JDK 动态代理;如果目标对象没有实现接口或者对性能要求不那么苛刻,可以选择 CGLIB 动态代理。默认情况下,Spring AOP 使用 JDK 动态代理,但在某些情况下会自动切换到 CGLIB 动态代理。

标签:JDK,spring,void,代理,切面,CGLIB,AOP,动态,public
From: https://www.cnblogs.com/hytip/p/18189286

相关文章

  • 微服务Spring Cloud17_Spring Cloud Gateway网关10
    一、简介SpringCloudGateway是Spring官网基于Spring5.0、SpringBoot2.0、ProjectReactor等技术开发的网关服务。SpringCloudGateway基于Filter链提供网关基本功能:安全、监控/埋点、限流等。SpringCloudGateway为微服务架构提供简单、有效且统一的API路由管理方式......
  • 谈谈 Spring 的过滤器和拦截器
    前言我们在进行Web应用开发时,时常需要对请求进行拦截或处理,故Spring为我们提供了过滤器和拦截器来应对这种情况。那么两者之间有什么不同呢?本文将详细讲解两者的区别和对应的使用场景。(本文的代码实现首先是基于SpringBoot,Spring的实现方式仅简单描述)1.过滤器1.1.......
  • 从XML配置角度理解Spring AOP
    本文分享自华为云社区《Spring高手之路18——从XML配置角度理解SpringAOP》,作者:砖业洋__。1.SpringAOP与动态代理1.1SpringAOP和动态代理的关系SpringAOP使用动态代理作为其主要机制来实现面向切面的编程。这种机制允许Spring在运行时动态地创建代理对象,这些代理对象包......
  • springmvc+swagger2+struts2
    jar包<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.7</version> </dependency> <dependency> <groupId>com.fasterxml.ja......
  • springboot内嵌tomcat的实现原理
    目录一、tomcat运行原理的简单分析1.1Coyote1.2容器catalina二、用编码的方式启动tomcat一、tomcat运行原理的简单分析tomcat运行时可以简单分成两个大的模块,(1)负责处理socket连接并转换成request对象的部分,连接器Coyote(2)处理用户的请求的容器Catalina下面简单介绍......
  • Spring6 的JdbcTemplate的JDBC模板类的详细使用说明
    1.Spring6的JdbcTemplate的JDBC模板类的详细使用说明@目录1.Spring6的JdbcTemplate的JDBC模板类的详细使用说明每博一文案2.环境准备3.数据准备4.开始4.1从数据表中插入(添加)数据4.2从数据表中修改数据4.3从数据表中删除数据4.4从数据表中查询一个对象4.5从数据表中......
  • spring注解开发
    要想使用注解,必须加入约束和相应配置<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="h......
  • 整合Spring Cloud + Nacos(服务注册与服务发现) + OpenFeign
    一、事前准备1、本文章不包含Nacos的安装教程,请参考其他文章安装并启动Nacos2、创建一个SpringBoot项目先创建一个简单的SpringBoot项目,引入普通项目中需要用到的相关依赖<dependencies><!--web--><dependency><groupId>org.springframework.boot</groupId......
  • spring中的IOC说明
    什么是IOC?控制反转,把对象创建和对象之间的调用过程交给spring进行管理,为了降低耦合度两种IOC接口BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象ApplicationContext:BeanFactory......
  • spring简介
    Spring是一个轻量级Java开发框架,最根本的使命是解决企业级应用开发的复杂性,即简化Java开发。Spring为企业级开发提供了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是控制反转(IOC)和面向切面编程(aspect-orientedprogramming,AOP)。spring框架包含的功能核......