Spring的核心AOP及代理模式(“最易懂得Spring学习”)(一)

简介: AOP1. 什么是AOP2. Aop在Spring中的作用3. 使用Spring实现AOP方式一:使用Spring的api接口[主要是api接口]方式二:自定义来实现aop[主要是切面]方式三:使用注解来实现aop

🐳点击送你到《简单了解了Spring以及IOC的理论推导》

🐳点击送你到《Spring中的IOC和DI》


AOP


1. 什么是AOP


AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性,同时提高了开发的效率。


AOP


  • 日志记录
  • 性能统计
  • 安全控制
  • 事务处理
  • 异常处理等


Spring AOP切面简单理解就是一把刀,在执行过程中可以随意地插入或拔出。


微信图片_20211230150123.png


2. Aop在Spring中的作用


提供声明式事务;允许用户自定义切面


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


微信图片_20211230150246.png

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


微信图片_20211230150229.png


3. 使用Spring实现AOP


【重点】使用AOP织入,需要导入一个依赖包


<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>
</dependencies>


方式一:使用Spring的api接口[主要是api接口]


UserService

package com.hxl.service;
public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

UserServiceImpl

package com.hxl.service;
public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("增加了一个用户");
    }
    public void delete() {
        System.out.println("删除了一个用户");
    }
    public void update() {
        System.out.println("修改了一个用户");
    }
    public void select() {
        System.out.println("查询了一个用户");
    }
}

applicationContext.xml

<?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:context="http://www.springframework.org/schema/context"
       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/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--注册bean-->
    <bean id="userService" class="com.hxl.service.UserServiceImpl"/>
    <bean id="log" class="com.hxl.log.Log"/>
    <bean id="afterLog" class="com.hxl.log.LogAfter"/>
    <!--使用原生的Spring API接口-->
    <!--配置aop:需要导入aop的约束-->
    <aop:config>
        <!--切入点;expression:表达式,execution(要执行的位置,修饰词,返回值,类名,方法名,参数)-->
        <aop:pointcut id="pointCut" expression="execution(* com.hxl.service.UserServiceImpl.*(..))"/>
        <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointCut"/>
    </aop:config>
</beans>

测试:

import com.hxl.service.UserService;
import com.hxl.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //注意点:动态代理代理的是接口
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}


方式二:自定义来实现aop[主要是切面]


DiyPointCut

package com.hxl.diy;
public class DiyPointCut {
    public void before(){
        System.out.println("====方法执行前====");
    }
    public void after(){
        System.out.println("====方法执行后====");
    }
}
<!--方式二:自定义类-->
<bean id="diy" class="com.hxl.diy.DiyPointCut"/>
<aop:config>
    <!--自定义切面,ref要引用的类-->
    <aop:aspect ref="diy">
        <!--切入点-->
        <aop:pointcut id="point" expression="execution(* com.hxl.service.UserServiceImpl.*(..))"/>
        <!--通知-->
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>


方式三:使用注解来实现aop


package com.hxl.diy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//方式三:使用注解方式实现aop
@Aspect//标注这个类是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.hxl.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("====方法执行前====");
    }
    @After("execution(* com.hxl.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("====方法执行后====");
    }
    //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* com.hxl.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("====环绕前====");
        Signature signature = jp.getSignature();//获得签名
        System.out.println("signature:" + signature);
        //执行方法
        Object proceed = jp.proceed();
        System.out.println("=====环绕后====");
    }
}
<!--方式三:-->
<bean id="annotationPointCut" class="com.hxl.diy.AnnotationPointCut"/>
<!--开启注解支持
    JDK(默认proxy-target-class="false")
    cglib(proxy-target-class="true")
    -->
<aop:aspectj-autoproxy />


相关文章
|
15天前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
6天前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
42 9
|
3天前
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
12 0
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
|
3天前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
5 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
3天前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
17 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
29天前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
2月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
29 0
Spring高手之路22——AOP切面类的封装与解析
|
2月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
44 0
|
24天前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
45 1
|
1月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
【9月更文挑战第9天】AOP(面向切面编程)通过分离横切关注点提高模块化程度,如日志记录、事务管理等。Micronaut AOP基于动态代理机制,在应用启动时为带有特定注解的类生成代理对象,实现在运行时拦截方法调用并执行额外逻辑。通过简单示例展示了如何在不修改 `CalculatorService` 类的情况下记录 `add` 方法的参数和结果,仅需添加 `@Loggable` 注解即可。这不仅提高了代码的可维护性和可扩展性,还降低了引入新错误的风险。
38 13