本文主要是介绍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代理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!