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

相关文章

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他

idea+spring boot创建项目的搭建全过程

《idea+springboot创建项目的搭建全过程》SpringBoot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目,:本文主要介绍idea+springb... 目录一.idea四种搭建方式1.Javaidea命名规范2JavaWebTomcat的安装一.明确tomcat

Git打标签从本地创建到远端推送的详细流程

《Git打标签从本地创建到远端推送的详细流程》在软件开发中,Git标签(Tag)是为发布版本、标记里程碑量身定制的“快照锚点”,它能永久记录项目历史中的关键节点,然而,仅创建本地标签往往不够,如何将其... 目录一、标签的两种“形态”二、本地创建与查看1. 打附注标http://www.chinasem.cn

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 多行数据