AOP系列(一)——ProxyFactoryObject 显式创建AOP代理

2024-05-25 10:48

本文主要是介绍AOP系列(一)——ProxyFactoryObject 显式创建AOP代理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

AOP概念

  Aspect Oriented Programming,面向切面编程,可以通过预编译方式和运行期动态代理,实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

前提


  • 了解Spring.NET IOC
  • 熟悉代理模式

  下面我们结合一个具体的例子来了解AOP。

基本情景

这里写图片描述

User类

    /// <summary>/// 用户实体,具有姓名和年龄两个属性/// </summary>public class User{public string Name { get; set; }public int Age { get; set; }}

IUserService

    public interface IUserService{//获得用户信息void GetUserInfo(User enUser);}

UserService

    public class UserService:IUserService{/// <summary>/// 获得用户的信息/// </summary>/// <param name="enUser">用户实体</param>public void GetUserInfo(User enUser){//输出用户的姓名和年龄Console.WriteLine("姓名:"+enUser .Name+"年龄:"+enUser .Age  );}}

客户端(控制台应用程序)Program

  • “ new()”出具体的实现——这里我们不采用此方式
    class Program{static void Main(string[] args){//实例化一个实体User enUser = new User(){Name = "Danny",Age = 15};           IUserService userService = new UserService();userService.GetUserInfo(enUser);}}
  • 通过Spring IOC获得具体实现(相当于工厂)
//引入Spring.Core.dll
using Spring.Context;
using Spring.Context.Support;namespace WithoutAOP
{class Program{static void Main(string[] args){//实例化一个实体User enUser = new User(){Name = "Danny",Age = 15};          //获得Spring.IOC容器的上下文IApplicationContext context = ContextRegistry.GetContext();//根据配置文件中的配置获得业务实现类IUserService userService = (IUserService)context.GetObject("userService");//调用业务实现类的方法userService.GetUserInfo(enUser);}}
}

配置文件

    <!--Spring配置--><configSections><sectionGroup name="spring"><section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/><section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/></sectionGroup></configSections><spring><context><resource uri="config://spring/objects"/></context><objects xmlns="http://www.springframework.net"><object id="userService" type="AOPExample.UserService,AOPExample"/></objects></spring>

  现在我们要为已有的业务逻辑增加日志功能。接下来看看AOP如何来实现。
  在了解之前,我们先来了解AOP中的一些术语。

AOP术语

这里写图片描述

  • 目标对象(Target),即我们要代理的对象(UserService),也就是我们要为此对象增加日志功能。
  • 关注点(Concern):如日志功能。日志功能是系统级别的,不可能只在一个对象中增加日志功能。
  • 通知(Advice):在Advice中写日志功能的具体实现。通知类实现不同的接口,如:Before,After……这些决定了日志功能如何添加(切入)到业务逻辑中,是在业务逻辑执行前添加,还是执行后添加。

AOP实现思路

  • 写具体的通知类Advice(实现日志功能)
  • 在配置文件中进行配置

    • 配置生成代理类的方式
    • 配置目标对象(可以直接配置具体的目标对象,也可以通过名称或正则表达式,程序执行后会在容器中寻找到符合条件的对象作为目标对象)

    • 配置通知类

ProxyFactoryObject 显式创建AOP代理

Advice通知类

//引入System.Aop.dll;
using Spring.Aop;       //AOP
using System.Reflection;//反射
namespace AOPExample
{/// <summary>/// Advice通知类:实现日志功能/// </summary>public class LogBeforeAdvice:IMethodBeforeAdvice{/// <summary>/// 实现接口IMethodBeforeAdvice中的Before方法,在目标方法执行前执行Before()/// </summary>/// <param name="method">拦截的方法</param>/// <param name="args">方法的参数</param>/// <param name="target">拦截的对象</param>public void Before(MethodInfo method, object[] args, object target){Console.WriteLine("拦截的方法名—>" + method.Name);Console.WriteLine("目标对象—>" + target);Console.WriteLine("参数—>");//如果参数不为空,遍历所有参数并输出if (args != null){foreach (object arg in args){Console.WriteLine("\t: " + arg);}}  }}
}

配置文件

<?xml version="1.0"?>
<configuration><!--Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常。--><!--注释掉此配置节,否则会报上述异常--><!--<startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /></startup>-->  <!--Spring配置--><configSections><sectionGroup name="spring"><section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/><section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/></sectionGroup></configSections><spring><context><resource uri="config://spring/objects"/></context><objects xmlns="http://www.springframework.net"><!--配置通知类LogBeforeAdvice--><object id="beforeAdvice" type="AOPExample.LogBeforeAdvice,AOPExample"/>         <!--通过ProxyFactoryObject 显式创建AOP代理--><object id="userServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject"><!--指定代理的真实对象--><property name="Target"><object type="AOPExample.UserService,AOPExample"/></property><!--指定具体通知类--><property name="InterceptorNames"><list><!--指定具体通知类,和前面配置的id一致--><value>beforeAdvice</value></list></property></object></objects></spring>
</configuration>

客户端

    class Program{static void Main(string[] args){//实例化用户User enUser = new User(){Name ="Jenny",Age=15};//获得Spring容器上下文IApplicationContext context = ContextRegistry.GetContext();//从配置文件获得由ProxyFactoryObject生成的代理类//需要修改客户端,原来是直接调用真实对象,现在是调用代理IUserService userServiceProxy = (IUserService)context["userServiceProxy"];userServiceProxy.GetUserInfo(enUser);}}

运行结果
这里写图片描述

总结

  • 优点:通过ProxyFactoryObject 创建代理类,省去自己手动创建代理类;
  • 缺点1:如果有多个目标对象,每个都需要在配置文件中配置;
  • 缺点2:客户端调用时,由原来调用目标对象,变成调用代理对象,需要修改客户端代码。

这篇关于AOP系列(一)——ProxyFactoryObject 显式创建AOP代理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1001289

相关文章

Spring创建Bean的八种主要方式详解

《Spring创建Bean的八种主要方式详解》Spring(尤其是SpringBoot)提供了多种方式来让容器创建和管理Bean,@Component、@Configuration+@Bean、@En... 目录引言一、Spring 创建 Bean 的 8 种主要方式1. @Component 及其衍生注解

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

MySQL 临时表创建与使用详细说明

《MySQL临时表创建与使用详细说明》MySQL临时表是存储在内存或磁盘的临时数据表,会话结束时自动销毁,适合存储中间计算结果或临时数据集,其名称以#开头(如#TempTable),本文给大家介绍M... 目录mysql 临时表详细说明1.定义2.核心特性3.创建与使用4.典型应用场景5.生命周期管理6.注

MySQL的触发器全解析(创建、查看触发器)

《MySQL的触发器全解析(创建、查看触发器)》MySQL触发器是与表关联的存储程序,当INSERT/UPDATE/DELETE事件发生时自动执行,用于维护数据一致性、日志记录和校验,优点包括自动执行... 目录触发器的概念:创建触www.chinasem.cn发器:查看触发器:查看当前数据库的所有触发器的定

创建springBoot模块没有目录结构的解决方案

《创建springBoot模块没有目录结构的解决方案》2023版IntelliJIDEA创建模块时可能出现目录结构识别错误,导致文件显示异常,解决方法为选择模块后点击确认,重新校准项目结构设置,确保源... 目录创建spChina编程ringBoot模块没有目录结构解决方案总结创建springBoot模块没有目录

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与