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

相关文章

idea中创建新类时自动添加注释的实现

《idea中创建新类时自动添加注释的实现》在每次使用idea创建一个新类时,过了一段时间发现看不懂这个类是用来干嘛的,为了解决这个问题,我们可以设置在创建一个新类时自动添加注释,帮助我们理解这个类的用... 目录前言:详细操作:步骤一:点击上方的 文件(File),点击&nbmyHIgsp;设置(Setti

Spring 中使用反射创建 Bean 实例的几种方式

《Spring中使用反射创建Bean实例的几种方式》文章介绍了在Spring框架中如何使用反射来创建Bean实例,包括使用Class.newInstance()、Constructor.newI... 目录1. 使用 Class.newInstance() (仅限无参构造函数):2. 使用 Construc

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

Spring-AOP-ProceedingJoinPoint的使用详解

《Spring-AOP-ProceedingJoinPoint的使用详解》:本文主要介绍Spring-AOP-ProceedingJoinPoint的使用方式,具有很好的参考价值,希望对大家有所帮... 目录ProceedingJoinPoijsnt简介获取环绕通知方法的相关信息1.proceed()2.g

Python中conda虚拟环境创建及使用小结

《Python中conda虚拟环境创建及使用小结》本文主要介绍了Python中conda虚拟环境创建及使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录0.前言1.Miniconda安装2.conda本地基本操作3.创建conda虚拟环境4.激活c

使用Python创建一个能够筛选文件的PDF合并工具

《使用Python创建一个能够筛选文件的PDF合并工具》这篇文章主要为大家详细介绍了如何使用Python创建一个能够筛选文件的PDF合并工具,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录背景主要功能全部代码代码解析1. 初始化 wx.Frame 窗口2. 创建工具栏3. 创建布局和界面控件4

Java中对象的创建和销毁过程详析

《Java中对象的创建和销毁过程详析》:本文主要介绍Java中对象的创建和销毁过程,对象的创建过程包括类加载检查、内存分配、初始化零值内存、设置对象头和执行init方法,对象的销毁过程由垃圾回收机... 目录前言对象的创建过程1. 类加载检查2China编程. 分配内存3. 初始化零值4. 设置对象头5. 执行

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

使用Python在Excel中创建和取消数据分组

《使用Python在Excel中创建和取消数据分组》Excel中的分组是一种通过添加层级结构将相邻行或列组织在一起的功能,当分组完成后,用户可以通过折叠或展开数据组来简化数据视图,这篇博客将介绍如何使... 目录引言使用工具python在Excel中创建行和列分组Python在Excel中创建嵌套分组Pyt