Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 1698|回复: 0

spring.net结合普通三层(实现IOC 及AOP中的异常记录功能)

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-8 16:58:34 | 显示全部楼层 |阅读模式

    首先先引用一下AOP相关知识;

    AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。
     
    OOP是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系;AOP是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。
     
    AOP是使用切面(aspect)将横切关注点模块化,OOP是使用类将状态和行为模块化。在OOP的世界中,程序都是通过类和接口组织的,使用它们实现程序的核心业务逻辑是十分合适。但是对于实现横切关注点(跨越应用程序多个模块的功能需求)则十分吃力,比如日志记录,验证等

     

    最近一直在学习spring.net的知识;结合先前学习的内容做一个跟普通三层相结合的实例;主要是演示spring.net中关于AOP的功能;首先了解一下我实例的项目架构;

    其中ISpringNetBLL,ISpringNetDAL分别为逻辑层跟数据层的接口层;因为本实例重点是运用结合spring.net所以代码都是非常简单;并无结合数据库的操作;

    具体代码分别如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ISpringNetBLL
    {
        //可以给BLL层定义一个统一的接口 然后再定义一个抽象类来继承接口
    
        public interface IUserOperate
        {
            string UserLogin(string UserName);
        }
    }
    

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;
    namespace ISpringNetBLL
    {
        public abstract class BaseBLL:IUserOperate
        {
            public BaseBLL()
            {
                
            }
    
            public abstract string UserLogin(string UserName);
        }
    }
    

      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ISpringNetDAL
    {
        public interface IUserOperateDAL
        {
            string UserLogin(string UserName);
        }
    }
    

    接下来我们看一下SpringNetAop层的内容;此层主要是实现一些AOP的代码,以及特性和一个统一调用spring.net的类;记录日志我们使用Log4Net来实现;

    1:Aspects 文件夹里存放的几个类分别是Spring.net几种AOP的通知模式;因为本实例主要是要演示异常的调用所以我们调用的是类LoggingThrowsAdvice.cs;有关Log4Net的运用大家可以搜索一下,不是本文的重点;这边有个要注意此处是类库运用Log4net,所以在读取配置文件时要写成@"bin\\Log4Net.config";而配置文件Log4Net.config属性要设置为:始终复制  嵌入的资源;

    using System.Linq;
    using System.Text;
    using SpringNetCommon;
    using System.Reflection;
    using Spring.Aop;
    using log4net;
    using log4net.Core;
    
    [assembly: log4net.Config.XmlConfigurator(ConfigFile = @"bin\\Log4Net.config", Watch = true)]
    namespace SpringNetAop.Aspects
    {
        public class LoggingThrowsAdvice:IThrowsAdvice
        {
            private ILog logger;
            public LoggingThrowsAdvice()
            {
                logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo("Log4Net.config"));
            }
    
            public void AfterThrowing(Exception ex)
            {
                logger.Warn(
                    String.Format("异常的内容为: {0}", ex));
            }
        }
    }
    

    Log4Net.config配置的内容如下:配置实现的功能是每天生成一个记录文件

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
      </configSections>
      <log4net>
        <appender name="RollingLogRootFileAppender" type="log4net.Appender.RollingFileAppender">
          <!--日志的路径-->
          <file value=".\Log\WanLog" />
          <!--是否覆盖,默认是追加true-->
          <appendToFile value="true"/>
          <!--文件滚动周期(每日创建新日志文件)-->
          <datePattern value="yyyyMMdd&quot;.txt&quot;"/>
          <!--设置无限备份=-1 ,最大备份数为1000-->
          <maxSizeRollBackups value="1000"/>
          <!--名称是否可以更改为false为可以更改-->
          <staticLogFileName value="false" />
          <!--文件滚动选项Composite表示根据日期和大小来滚动-->
          <rollingStyle value="Composite" />
          <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}[%t][%-5p][%c]%m%n%exception%n" />
          </layout>
        </appender>
        <root>
          <level value="All" />
          <appender-ref ref="RollingLogRootFileAppender" />
        </root>
      </log4net>
    </configuration>


    2:Attributes存放的是一个重写的特性;spring.net特性来定位要调用AOP;这边主要注意是要继承Attribute;

    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SpringNetAop.Attributes
    {
        public class LoggingAttributes:Attribute
        {
            public LoggingAttributes()
            {
     
            }
        }
    }

    3:SpringNetHelp文件夹存放的是一个统一调用spring.net的类;因为我把spring.net的配置文件存放在UI层;所以要注意调用的路径问题;配置文件我们在UI层进行;

    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;
    using Spring.Core.IO;
    using Spring.Objects.Factory;
    using Spring.Objects.Factory.Xml;
    namespace SpringNetAop.SpringNetHelp
    {
        public class GetAppContext
        {
            private static IApplicationContext applicationContext = null;
    
            public GetAppContext()
            {
     
            }
    
            public static IApplicationContext ApplicationContext
            {
                get
                {
                    applicationContext = new XmlApplicationContext("~/Config/Objects.xml");
                    return applicationContext;
                }
            }
        }
    }


    接下来我们看一下逻辑层跟数据层的代码;

    首先看一下数据层的代码;我们为要进行异常记录的方法加上特性[LoggingAttributes]

    using System.Linq;
    using System.Text;
    using ISpringNetDAL;
    using SpringNetAop.Attributes;
    namespace SpringNetDAL
    {
        public class UserOperateDAL:IUserOperateDAL
        {
            [LoggingAttributes]
            public string UserLogin(string UserName)
            {
                 throw new Exception("我是DAL层的异常");
            }
        }
    }

    看BLL层的具体代码如下:

    using Spring.Core;
    using SpringNetAop;
    using Spring.Core.IO;
    using Spring.Objects.Factory.Xml;
    using Spring.Objects.Factory;
    using Spring.Context.Support;
    using Spring.Context;
    namespace SpringNetBLL
    {
        public class UserOperate:BaseBLL
        {
            private IUserOperateDAL _userOperatedal = null;
    
            public UserOperate()
            {
            }
    
            [LoggingAttributes]
            public override string UserLogin(string UserName)
            {
                // throw new Exception("我是BLL层异常内容啊");
                 _userOperatedal = (IUserOperateDAL)SpringNetAop.SpringNetHelp.GetAppContext.ApplicationContext.GetObject("UserOperateDal");
                 return _userOperatedal.UserLogin(UserName);   
            }
        }
    }


    接着看一下UI层;这边主要是两个配置文件就是Objects.xml 以及App.config; 其中Objects.xml文件的属性设置:始终复制  生成操作为内容;

    App.config的内容如下(关于spring.net配置的说明大家可以搜索园内的spring.net知识或者可以查看spring.net提供的帮助手册,都有很详细的说明):

    <?xml version="1.0"?>
    <configuration>
    
      <configSections>
        <sectionGroup name="spring">
          <!--提供Spring对应用程序上下文的支持-->
          <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
          <!--提供Spring对 对象容器的支持-->
          <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
        </sectionGroup>
      </configSections>
    
      <spring>
        <context>
          <resource uri="file://~/Config/Objects.xml"/>
          <!--<resource uri="assembly://SpringNetUI/SpringNetUI.Config/Objects.xml"/>-->
        </context>
      </spring>
      
    </configuration>

    Objects.xml文件的内容:

    <?xml version="1.0" encoding="utf-8" ?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
      <object name="UserOperateDal" type="SpringNetDAL.UserOperateDAL,SpringNetDAL"/>
      
      <!--环绕通知拦截  运用特性-->
      <object id="aroundAdvisor" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice">
          <object type="SpringNetAop.Aspects.LoggingAroundAdvice, SpringNetAop" />
        </property>
        <property name="Attribute"
                  value="SpringNetAop.Attributes.LoggingAttributes, SpringNetAop" />
      </object>
    
      
      <!--后置通知拦截  运用名称-->
      <object id="afterAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice">
          <object type="SpringNetAop.Aspects.LoggingAfterAdvice, SpringNetAop" />
        </property>
        <property name="MappedNames">
          <list>
            <value>*UserLogin</value>
          </list>
        </property>
      </object>
    
      <!--异常通知拦截  程序所有都支持 不设置条件-->
      <object id="throwsAdvice"  type="SpringNetAop.Aspects.LoggingThrowsAdvice, SpringNetAop" />
      
      
    
      <object id="myServiceCommand" type="Spring.Aop.Framework.ProxyFactoryObject">
        <property name="Target">
          <object type="SpringNetBLL.UserOperate, SpringNetBLL" />
        </property>
        <property name="InterceptorNames">
          <list>
            <value>aroundAdvisor</value>
            <value>afterAdvisor</value>
            <value>throwsAdvice</value>
          </list>
        </property>
      </object>
    </objects>


    UI层调用BLL的代码;使用的是Spring.net的IOC

    using Spring.Context;
    using Spring.Context.Support;
    using Spring.Core.IO;
    using Spring.Objects.Factory.Xml;
    using Spring.Objects.Factory;
    using ISpringNetBLL;
    using SpringNetAop;
    using SpringNetBLL;
    namespace SpringNetUI
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    IUserOperate command = (IUserOperate)SpringNetAop.SpringNetHelp.GetAppContext.ApplicationContext.GetObject("myServiceCommand");
                    command.UserLogin(this.textBox1.Text.Trim());
                }
                catch
                {
    
                }
            }
    
        }
    }


    运行程度得到的结果如下:

    2013-04-06 22:28:57[1][WARN ][SpringNetAop.Aspects.LoggingThrowsAdvice]异常的内容为: System.Exception: 我是DAL层的异常
       在 SpringNetDAL.UserOperateDAL.UserLogin(String UserName) 位置 F:\测试网址\SpringNETDemo\SpringNetDAL\UserOperateDAL.cs:行号 14
       在 SpringNetBLL.UserOperate.UserLogin(String UserName) 位置 F:\测试网址\SpringNETDemo\SpringNetBLL\UserOperate.cs:行号 30
       在 _dynamic_SpringNetBLL.UserOperate.UserLogin(Object , Object[] )
       在 Spring.Reflection.Dynamic.SafeMethod.Invoke(Object target, Object[] arguments)
       在 Spring.Aop.Framework.DynamicMethodInvocation.InvokeJoinpoint()
       在 Spring.Aop.Framework.AbstractMethodInvocation.Proceed()
       在 Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor.Invoke(IMethodInvocation invocation)

     

    本文的内容是个人学习spring.net的知识,若有错误的地方欢迎指正;

    源代码下载:http://download.csdn.net/detail/u010127054/5227385

     

    最近有个妹子弄的一个关于扩大眼界跟内含的订阅号,每天都会更新一些深度内容,在这里如果你感兴趣也可以关注一下(嘿对美女跟知识感兴趣),当然可以关注后输入:github 会有我的微信号,如果有问题你也可以在那找到我;当然不感兴趣无视此信息;

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-23 01:36 , Processed in 0.056347 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表