《深入理解AOP编程:从基础概念到Spring实现》

AOP编程

AOP(Aspect Oriented Programing) 面向切面编程 =Spring动态代理开发

以切面为基本单位的程序开发,通过切脉你间的彼此协同,相互调用,完成程序构建

切面=切入点+额外功能


OOP(Object Oriented Programing)面向对象编程 java
以对象为基本单位的程序开发,通过对象间的彼此协同,相互调用,完成程序构建


POP(Procedure Oriented Programing)面向过程(方法、函数)编程

以过程为基本单位程序开发,通过过程间的彼此协同,相互调用,完成程序构建

AOP概念

        本质是Spring的动态代理开发,通过代理类为原始类增加额外功能

        好处:利于原始类的维护

注意:AOP编程不可能取代OOP OOP编程的补充

 AOP编程开发步骤

1.原始对象

2.额外功能

3.切入点

4.组装切面(额外功能+切入点)

名词解释

切面=切入点+额外功能
 

几何学

        面=点+相同性质

             方法+相同的功能

 AOP底层实现原理

1.核心问题

1.AOP如何创建动态代理类(动态字节码技术)

2.Spring工厂如何加工创建代理对象

        通过原始对象的id值,获得是代理对象

 2.动态代理类的创建

 2.1JDK动态代理

类加载器作用:ClassLoader

1.通过类加载器把对应类的字节码文件加载倒JVM

2.通过类加载器创建类的Class对象,进而创建这个类的对象

User--->user

User类Class对象 --->new User() -->user

如何获得类加载器:每一个类的.class文件 自动分配与之对应的ClassLoader


public class TestJDKProxy {/*借类加载器 可以借用其它类*/public static void main(String[] args) {//创建原始对象UserService userService=new UserServiceImpl();//JDK创建动态代理InvocationHandler handler=new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理功能");Object ret=method.invoke(userService,args);return ret;}};UserService userServiceProxy=(UserService) Proxy.newProxyInstance(TestJDKProxy.class.getClassLoader(),userService.getClass().getInterfaces(),handler);userServiceProxy.register(new proxy.User("zhangsan","123456"));}
}

2.2 CGlib动态代理

 CGlib创建动态代理原理:父子继承关系创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证二者方法一致,同时在代理类中提供新的实现(额外功能+原始方法)

package jdkProxy;import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.Proxy;import java.lang.reflect.Method;public class TestCGlib {public static void main(String[]args){//创建原始对象UserService userService=new UserService();//通过cglib方式创建动态代理对象//Proxy.newProxyInstance(); 不需要接口Enhancer enhancer = new Enhancer();enhancer.setClassLoader(TestCGlib.class.getClassLoader());enhancer.setSuperclass(UserService.class);//父类是原始对象MethodInterceptor interceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("cglib 代理功能");Object result = method.invoke(userService,args);return result;}};enhancer.setCallback(interceptor);UserService userServiceProxy = (UserService) enhancer.create();userServiceProxy.login("zhangsan","123456");}
}

 总结

JDK动态代理 Proxy.newProxyInstance() 通过接口创建代理的实现类

Cglib动态代理 Enhancer

Spring工厂如何加工原始对象

 编码

package factory;import org.springframework.beans.factory.config.BeanPostProcessor;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class ProxyBeanPostProcessor implements BeanPostProcessor {public Object postProcessBeforeInitialization(Object bean, String beanName) {return bean;}public Object postProcessAfterInitialization(Object bean, String beanName){InvocationHandler handler=new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("-----额外功能——-------");Object ret=method.invoke(bean,args);return ret;}};return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),bean.getClass().getInterfaces(),handler);}}<bean id="userService" class="factory.UserServiceImpl"></bean>
<!--1.实现配置BeanPostProcessor 进行加工2.配置文件中对BeanPostProcessor配置
-->     <bean id="proxyBeanPostProcessor" class="factory.ProxyBeanPostProcessor"></bean>

基于注解的AOP编程
1.基于注解的AOP编程开发步骤

  1. 1.原始对象
  2. 2.额外功能
  3. 3.切入点
  4. 4.组装切面

#通过切面类 定义了 额外功能@Around

                     定义了 切入点 @Around("execution *login(..)")

                     @Aspect 切面类

package aspect;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;@Aspect
/*1.额外功能public class MyArround implements MethodInterceptor {public Object invoke(MethodInvocation methodInvocation) throws Throwable{Obejct ret=methodInvocation.proceed();return ret;}}2.切入点<aop config<aop:pointcut id="" expression="execution(* *(..))"/>*/
public class MyAspect {@Around("execution(* *(..))")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("around");Object ret=joinPoint.proceed();return ret;}
}
<?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 https://www.springframework.org/schema/aop/spring-aop.xsd"><aop:aspectj-autoproxy/><bean id="userService" class="aspect.UserServiceImpl"></bean>
<!--1.额外功能2.切入点3.组装切面
--><bean id="arround" class="aspect.MyAspect"></bean><!--    告知spring基于注解进行编程--></beans>

细节

切入点复用

切入点复用:在切面类中定义一个函数,上面@Pointcut注解,通过这种方式,定义切入点表达式,后面更有利于切入点复用

public class MyAspect {@Pointcut("execution(* *(..))")public void myPointcut(){};@Around(value = "myPointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("around");Object ret=joinPoint.proceed();return ret;}@Around(value = "myPointcut()")public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("around1");Object ret=joinPoint.proceed();return ret;}
}

 动态代理 创建方式

AOP底层实现 2种代理创建方式

1.JDK 通过实现接口 新的实现 创建代理对象

2.Cglib通过继承父类 做新的子类 创建代理对象


默认情况 AOP编程 底层应用JDK动态代理创建方式

如果切换Cglib

1.基于注解AOP开发

        

<aop:aspectj-autoproxy proxy-target-class="true"/>

2.传统AOP开发

 <aop:config proxy-target-class="true">
<!--        所有的方法 都作为切入点 加入额外功能 login register--><aop:pointcut id="pc" expression="execution(* *(..))"/><aop:advisor advice-ref="arround" pointcut-ref="pc"></aop:advisor></aop:config>

   

AOP开发中的坑

坑:同一个业务类中,进行业务方法间的相互调用 只有最外层方法,才是加入了额外功能(内部方法,通过普通方式调用,都调用的是原始方法) 如果想让内层方法也调用代理对象方法,ApplicationContextAware获得工厂,进而获得对象

package aspect;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;public class UserServiceImpl implements UserService, ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void login(String username, String password) {System.out.println("login");}@Overridepublic void register(String username, String password) {System.out.println("register");UserService userService = applicationContext.getBean("userService", UserService.class);userService.login("zhangsan", "123456");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext=applicationContext;}
}

AOP总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 零基础入门篇(19.DateTime 使用指南)

## 一、概述 DateTime 是 C# 中用于表示日期和时间的结构&#xff0c;位于 System 命名空间中。它提供了丰富的属性和方法&#xff0c;用于处理日期和时间的创建、格式化、比较和计算。 ## 二、创建 DateTime 对象 ### &#xff08;一&#xff09;使用默认构造函数 DateTime…

Docker 实践与应用举例

一、引言 在当今快速发展的信息技术领域&#xff0c;容器化技术已成为推动软件开发、部署和运维变革的关键力量。Docker 作为容器化技术的领军者&#xff0c;以其高效、便捷、可移植等特性&#xff0c;被广泛应用于各种场景。它能够将应用程序及其依赖项打包成一个独立的容器&…

C++初阶——类和对象(一)

C初阶——类和对象&#xff08;一&#xff09; 一、面向过程和面向对象 1.面向过程 面向过程的程序设计&#xff08;Procedure-Oriented Programming&#xff09;&#xff0c;简称POP&#xff0c;是一种是以程序执行流程为核心的编程范式。它是先分析出解决问题所需要的的步…

Skyeye 云智能制造办公系统 VUE 版本 v3.15.13 发布

Skyeye 云智能制造&#xff0c;采用 Springboot winUI 的低代码平台、移动端采用 UNI-APP。包含 30 多个应用模块、50 多种电子流程&#xff0c;CRM、PM、ERP、MES、ADM、EHR、笔记、知识库、项目、门店、商城、财务、多班次考勤、薪资、招聘、云售后、论坛、公告、问卷、报表…

Obsidian Copilot:打造你的专属 AI 笔记助手

Obsidian Copilot作为一款非常受欢迎的Obsidian插件&#xff0c;不仅极大地提升了用户的笔记管理和信息检索效率&#xff0c;还通过其多样化的AI功能为用户带来了前所未有的便捷体验。本文将详细介绍Obsidian Copilot的核心特点、使用方法及个人体验分享。 核心特点 Obsidian…

每日一题--计算机网络

一、基础概念类问题 1. TCP 和 UDP 的区别是什么&#xff1f; 回答示例&#xff1a; TCP&#xff1a;面向连接、可靠传输&#xff08;通过三次握手建立连接&#xff0c;丢包重传&#xff09;、保证数据顺序&#xff08;如文件传输、网页访问&#xff09;。 UDP&#xff1a;无…

使用 Spring 的 FactoryBean 创建和获取 Bean 对象

在Spring框架中&#xff0c;FactoryBean接口提供了一种强大的机制来创建复杂的bean实例。本文将基于提供的代码示例&#xff0c;详细介绍如何通过FactoryBean创建bean对象&#xff0c;并展示如何获取这些bean实例以及它们所属的FactoryBean实例。 示例代码类 定义 MyBean 接口…

制造业数字化转型,汽车装备制造企业数字化转型案例,智能制造数字化传统制造业数字化制造业数字化转型案例

《某制造业企业信息化整体解决方案》PPT展示了一个汽车装备企业的整体信息化解决方案&#xff0c;阐述了该企业的业务特点和现状&#xff0c;主要包括按订单生产、多级计划和产品跟踪等&#xff0c;分析了信息化建设的主要困难&#xff0c;如信息管理手工化、过程数据追溯困难、…

软链接 使用笔记 linux命令 if判断

目录 1>0判断怎么写&#xff1a; 1. 使用 [ ] 进行数值比较&#xff1a; 2. 使用 (( )) 进行数学运算&#xff1a; 3. 使用 [[ ]]&#xff08;主要用于字符串比较&#xff0c;不推荐用于数学运算&#xff09;&#xff1a; 软链接 使用笔记 1>0判断怎么写&#xff1a…

pycharm-python國際象棋遊戲代碼

嗯&#xff0c;用户的问题是“pycharm寫關於python國際象棋遊戲代碼”&#xff0c;也就是要用PyCharm来写一个Python的国际象棋游戏代码。我需要先整理一下用户提供的搜索结果&#xff0c;看看有什么相关的信息可以利用。 首先看搜索结果中的各个网页内容。网页1主要讲的是象棋…

【Film】MovieAgent:自动化电影生成通过多智能体CoT规划

论文概览 自动化电影生成根据剧本概要和角色库创建具有一 致角色、同步字幕和音频的长篇视频。它涉及自动化叙 事规划、场景结构化, 和镜头构图,复制现实世界电影制作的层次推理。 核心贡献 提出MovieAgent,通过多智能体链式思维(CoT)规划实现自动化电影生成。首次探索并…

数据结构——最短路(BFS,Dijkstra,Floyd)

完整版可以看我的最短路问题模版总结_稠密图最短路-CSDN博客 考研数据结构只考BFS,Dijkstra和Floyd 下面代码以Acwing模板题为例 BFS代码 适用类型&#xff1a; 1.单源最短路径 2.无权图 3.不适用于带权图和负权回路图 //Acwing走迷宫bfs #include<bits/stdc.h>usi…

ftp替代品,如何提升数据交换的安全性与高效性?

文件传输协议&#xff08;FTP&#xff09;是一个跨平台的、简单且易于实现的协议&#xff0c;用于在网络上的服务器和客户端之间传输文件&#xff0c;也是企业会经常选择的一种传输方式。 业务场景一&#xff1a; 基于信息相关安全要求&#xff0c;医院会采用防火墙、网闸等将…

单片机开发资源分析的实战——以STM32G431RBT6为例子的单片机资源分析

目录 第一点&#xff1a;为什么叫STM32G431RBT6 从资源手册拿到我们的对STM32G431RBT6的资源描述 第二件事情&#xff0c;关心我们的GPIO引脚输出 第三件事情&#xff1a;去找对应外设的说明部分 第一点&#xff1a;为什么叫STM32G431RBT6 对于命名规则不太熟悉的朋友看这里…

Android PC 要来了?Android 16 Beta3 出现 Enable desktop experience features 选项

在之前的 《Android 桌面窗口新功能推进》 我们就聊过&#xff0c;Google 就一直在努力改进 Android 的内置桌面模式&#xff0c;例如添加了适当的窗口标题、捕捉窗口的能力、悬停选项、窗口大小调整、最小化支持、app-to-web 等。 比如在搭载 Android 15 QPR 1 Beta 2 的 Pix…

IP关联是什么?怎么避免?

在跨境电商的道路上&#xff0c;大家好&#xff01;今天想和大家聊一聊一个非常重要的话题&#xff0c;那就是IP关联的问题。在商业活动中&#xff0c;了解如何避免IP关联对保护我们宝贵的商铺至关重要。接下来&#xff0c;我们将深入探讨IP关联的概念、影响及如何有效防止这一…

行为模式---状态模式

概念 状态模式是一种行为模式&#xff0c;用于在内部状态改变的时候改变其行为。它的核心思想就是允许一个对象在其内部状态改变的时候改变它的行为。状态模式通过将对象的状态封装成独立的类&#xff0c;并将其行为委托给当前的状态对象&#xff0c;从而使得对象行为随着状态…

目标检测中衡量模型速度和精度的指标:FPS和mAP

“FPS”和“mAP”分别衡量了模型的速度和精度。 FPS&#xff08;Frames Per Second&#xff09; 定义&#xff1a;FPS是“每秒传输帧数”的缩写&#xff0c;用于衡量计算机视觉系统&#xff08;如目标检测、图像识别等&#xff09;的实时性能。它表示系统每秒钟能够处理的图像…

网页复印机:只需一个网址,一键克隆任何网站!(可根据需求生成/优化相关代码)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 网页代码克隆神器:一键复刻精美设计,提升前端开发效率 📒🛠️ 使用⚓️ 相关链接 ⚓️📖 介绍 📖 每天对着别人的精美网站漏出羡慕的眼神,却苦于自己的前端技术不够硬,难以完美复刻?或者为了赶项目进度,不得不重复…

go语言中数组、map和切片的异同

在Go语言中&#xff0c;数组、切片&#xff08;slice&#xff09;和映射&#xff08;map&#xff09;是三种常用的数据结构&#xff0c;它们在用途和特性上有显著差异。以下是它们的异同总结&#xff1a; 相同点 集合类型&#xff1a;三者都用于存储一组数据。 元素访问&#…