ABP入门系列目录——学习Abp框架之实操演练

源码路径:Github-LearningMpaAbp


1. 引言

现在的互联网已不在仅仅局限于网页应用,IOS、Android、平板、智能家居等平台正如火如荼的迅速发展,移动应用的需求也空前旺盛。所有的互联网公司都不想错过这一次移动浪潮,布局移动市场分一份移动红利。

的确,智能手机作为我们日常生活已必不可少的一部分,通过手机app能够获得更好的体验,比如社交、购物、娱乐、生活。

但这也引入了一个问题,如果布局移动市场,就意味着要维护好几条产品线,比如网页、Android、IOS、微信公众号等。这对公司来说无疑是一项大的投入。

产品对于用户来说,用户只关心体验。

而对于开发者来说,开发者更关心在保证业务流程及数据的正确流转下,如何对产品线进行集成,来避免做重复工作。

而恰好ABP框架就已经帮我们解决了这一问题,Abp是基于【模块化设计思想】构建的,开发人员可以将自定义的功能以模块(module)的形式集成到ABP中。

不同的模块通过组装就可以组成一个新的功能。

那你肯定很好奇如何玩转Abp模块,下面我们就以我们的Demo为例,来进行微信公众号模块的开发。

2. 创建微信公众号模块

定义一个模块很简单,只需创建微信项目,然后定义WeixinModule类继承自AbpModule即可,再然后为WeixinModule定义[DependsOn]特性指定依赖的模块即可。

2.1. 创建微信公众号项目

新建mvc项目,命名项目名为LearningMpaAbp.Weixin。因为要使用到Abp定义的模块功能,首先要安装Abp Nuget包,选择后会提示需要以下Nuget包,点击确定安装即可。

2.2. 定义微信公众模块

新建LearningMpaAbpWeixinModule继承自AbpModule。代码如下:

public class LearningMpaAbpWeixinModule:AbpModule
{
/// <summary>
/// 预初始化,通常是用来配置框架以及其它模块
/// </summary>
public override void PreInitialize()
{
base.PreInitialize();
} /// <summary>
/// 初始化,一般用来依赖注入的注册
/// </summary>
public override void Initialize()
{
//把当前程序集的特定类或接口注册到依赖注入容器中
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
} /// <summary>
/// 提交初始化,一般用来解析依赖关系
/// </summary>
public override void PostInitialize()
{
base.PostInitialize();
} /// <summary>
/// 应用关闭时调用
/// </summary>
public override void Shutdown()
{
base.Shutdown();
}
}

从代码中可以看出主要包括四个重载方法,每个重载方法负责不同的职责。

2.3. 指定依赖模块

因为我们需要通过webapi与现有demo进行交互,所以还需要安装Abp.Web.Api Nuget包。

那怎样指定依赖呢,只需要通过[DependsOn]特性指定即可。

[DependsOn(typeof(AbpWebApiModule))]
public class LearningMpaAbpWeixinModule:AbpModule
{
//....
}

好了,一个微信公众号模块的基础项目框架搭好了,是不是很简单!

到这一步,你可能会问,你这只是简单创建微信公众号模块,但如何与我们Demo进行集成交互呢?

对的,是只简单创建了微信模块,但这一节我不打算讲如何与Demo进行集成交互。因为在介绍如何通过webapi与系统交互之前,梳理下Abp模块化的设计,更能帮助我们了解模块化设计思想。

下面我们就简单梳理下ABP模块化的设计。

3. ABP模块化设计

说到模块,突然想到几个单词考考大家,model、modal、module分别是什么意思?

不知道的就自行查词典吧。

下面回归正题。

3.1. 模块化相关类型

先来看看模块相关类型依赖图:

从类型依赖图中可以看出设计的并不复杂:

  • AbpModule:所有定义的模块均需继承此抽象类。
  • AbpModuleInfo:可以理解为AbpModule的元数据,封装AbpModule的基本信息,主要包括Assembly(所属程序集)、Type(类型)、Dependencies(依赖的模块)、IsLoadedAsPlugIn(是否插件模块)。
  • AbpModuleCollection:从类的申明:class AbpModuleCollection : List可知它是一个AbpModuleInfo的集合。
  • AbpModuleManager:模块管理类,主要用来进行模块管理,比如启动关闭模块。
  • DependsOnAttribute:依赖特性,用来标明模块的依赖项。

3.2. Abp如何发现并加载模块

Abp中定义了一个启动类AbpBootstraper,该类的职责是启动整个Abp系统,主要负责依赖注入和注册模块以供启动。而该类必须在应用程序启动时最先被实例化。

而作为Abp生成的模板项目,启动项目自然是web应用,所以AbpBootstrapper肯定在Web项目中被初始化。众所周知,web项目的启动是从Global.asax文件的Application_Start项目开始的。

public class MvcApplication : AbpWebApplication<LearningMpaAbpWebModule>
{
protected override void Application_Start(object sender, EventArgs e)
{
AbpBootstrapper.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.UseAbpLog4Net().WithConfig("log4net.config")
); base.Application_Start(sender, e);
}
}

我们先来观察下类的申明,有没有发现什么特别之处?

继承的是泛型基类且指定的泛型为LearningMpaAbpWebModule,指定了一个Module,当前web项目的Moduel。

对MVC比较熟悉的同学应该知道,MVC应用程序启动类默认是继承自HttpApplication的。从该段代码可以看出,Abp修改了MvcApplication的默认继承类。那自然AbpWebApplication<T>是继承自HttpApplication了。废话不多说,来看一看具体的定义:

public abstract class AbpWebApplication<TStartupModule>
: HttpApplication where TStartupModule : AbpModule
{
/// <summary>
/// Gets a reference to the <see cref="P:Abp.Web.AbpWebApplication`1.AbpBootstrapper" /> instance.
/// </summary>
public static AbpBootstrapper AbpBootstrapper { get; } = AbpBootstrapper.Create<TStartupModule>(); /// <summary>
/// This method is called by ASP.NET system on web application's startup.
/// </summary>
protected virtual void Application_Start(object sender, EventArgs e)
{
ThreadCultureSanitizer.Sanitize();
AbpWebApplication<TStartupModule>.AbpBootstrapper.Initialize();
} /// <summary>
/// This method is called by ASP.NET system on web application shutdown.
/// </summary>
protected virtual void Application_End(object sender, EventArgs e)
{
AbpWebApplication<TStartupModule>.AbpBootstrapper.Dispose();
}
//省略了部分代码
}

首先映入眼帘的是基类中定义的AbpBootstraper属性,然后看到的是Application_StartApplication_End虚方法。

Application_Start方法中调用了AbpBootstrapper.Initialize()方法。相当于AbpBootstrapper.Create<TStartupModule>().Initialize();

代码是不是看累了,上图,咱们直接来看web项目启动时Module动态加载的调用堆栈。

是不是一目了然,总结以下:

Abp在启动项目时根据指定的启动模块(StartupModule)首先加载该模块,然后再去检查该模块的自定义特性是否定义有[DependsOn]特性,若有则按序加载所有依赖的模块,也就是链式动态依赖加载。然后再依次调用Module的PreInitialize,Initialize和PostInitialize以完成初始化。

好了模块的启动加载就讲到这里,感兴趣的还是建议大家直接看看源码。

这里推荐一篇文章ABP源码分析三:ABP Module,来帮助大家理解Abp的模块化思想。

4. 总结

这一节有点标题党的味道,但内容也算点题了。下一篇我将介绍微信公众号模块如何通过WebApi与系统进行交互,尽情期待。

ABP入门系列(15)——创建微信公众号模块的更多相关文章

  1. 【原创】【2015最新】微信公众平台开发手把手入门之一:缘起微信公众号(PHP,MYSQL, BAE)

    最近因为业务的需要,老板布置做了两个月简单的的微信公众平台开发,从网上搜了一些资料,实话说资料不多. 在参考学习的过程中也遇到了不少难缠的小问题,虽然不难逾越,但是确实浪费了时间. 我发现网上仅有不多 ...

  2. 带领技术小白入门——基于java的微信公众号开发(包括服务器配置、java web项目搭建、tomcat手动发布web项目、微信开发所需的url和token验证)

    微信公众号对于每个人来说都不陌生,但是许多人都不清楚是怎么开发的.身为技术小白的我,在闲暇之余研究了一下基于java的微信公众号开发.下面就是我的实现步骤,写的略显粗糙,希望大家多多提议! 一.申请服 ...

  3. 14、ABPZero系列教程之拼多多卖家工具 新建微信公众号模块

    说是模块,其实在MVC中就是区域,新建一个区域专门管理整个微信功能. Web项目新建区域 在Web项目Areas目录下新建一个区域,名称为“Weixin",如下图: 接着打开web.conf ...

  4. ABP入门系列目录——学习Abp框架之实操演练

    ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WE ...

  5. ABP入门系列(16)——通过webapi与系统进行交互

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 引言 上一节我们讲解了如何创建微信公众号模块,这一节我们就继续跟进,来讲一讲公众号模块如何与 ...

  6. 微信公众号开发C#系列-12、微信前端开发利器:WeUI

    1.前言 通过前面系列文章的学习与讲解,相信大家已经对微信的开发有了一个全新的认识.后端基本能够基于盛派的第三方sdk搞定大部分事宜,剩下的就是前端了.关于手机端的浏览器的兼容性问题相信一直是开发者们 ...

  7. 微信公众号开发系列-13、基于RDIFramework.NET框架整合微信开发应用效果展示

    1.前言 通过前面一系列文章的学习,我们对微信公众号开发已经有了一个比较深入和全面的了解. 微信公众号开发为企业解决那些问题呢? 我们经常看到微信公众号定制开发.微信公众平台定制开发,都不知道这些能给 ...

  8. 使用NW.js封装微信公众号菜单编辑器为桌面应用

    开发微信公众号的朋友都会遇到一个常见的需求就是修改自定义菜单,如果每个人都去开发这个不经常使用的功能确实有点浪费时间.前段时间在github上找到一个仿企业号的菜单编辑界面,结合微信的C# SDK开发 ...

  9. 微信公众号菜单openid 点击菜单即可打开并登录微站

    现在大部分微站都通过用户的微信openid来实现自动登录.在我之前的开发中,用户通过点击一个菜单,公众号返回一个图文,用户点击这个图文才可以自动登录微站.但是如果你拥有高级接口,就可以实现点击菜单,打 ...

随机推荐

  1. 用《内网穿山甲》把本地IIS中的站点共享到远程访问

    前言: 因为各种原因,我们常常要把本机或局域网中搭建的站点发给远方的人访问,他有可能是测试人员.客户.前端.或领导演示,或是内部系统内部论坛临时需要在远程访问,事件变得很麻烦,要么有公网IP,要么能控 ...

  2. Spark RDD编程核心

    一句话说,在Spark中对数据的操作其实就是对RDD的操作,而对RDD的操作不外乎创建.转换.调用求值. 什么是RDD RDD(Resilient Distributed Dataset),弹性分布式 ...

  3. [solr] - solr5.2.1环境搭建 - 使用tomcat做为容器

    这里忽略solr其他依赖环境的搭建,这里搭建solr5.2.1.使用Java1.7.0_17,tomcat使用6.0.36版本的. 1.下载solr压缩文件 Solr是Apache基金组织在lucen ...

  4. redis主从切换的集群管理

    集群配置最少需要三台机器,那么我就三台虚拟机,三台虚拟机分别安装同样的redis的环境ip分别:192.168.9.17 (redis sentinel 集群监控)192.168.9.18 (redi ...

  5. java基础之路(二)上

    &和&&的区别 我们今天就来说一下&与&&运算符的区别 &运算符有两种用法:(1)按位与:(2)逻辑与.&&运算符是短路与运算. ...

  6. react 组件的生命周期

    组件的生命周期 过程 装载(Mounting) :组件被插入到 DOM 中: 更新(Updating) :组件重新渲染以更新 DOM: 卸载(Unmounting) :组件从 DOM 中移除. 过程 ...

  7. Oracle 字符集设置

    因为装Linux系统时选择的是英文版,所以当需要测试中文数据库时会出现乱码,这里记录一下我修改字符集的操作. 一些命令: 1.查看sqlplus客户编码: $ echo  $NLS_LANG 2.查看 ...

  8. vue组件最佳实践

    看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...

  9. asp.net mvc源码分析-Route的GetRouteData

    我知道Route这里东西应该算路由,这里把它放到mvc里面有些不怎么合适,但是我想大家多数遇到路由都是在mvc的时候吧.首先我们还是来看看GetRouteData方法吧 [csharp] public ...

  10. 为什么每个浏览器User-Agent都是Mozilla?真相原来是这样!

    转载自简明现代魔法http://www.nowamagic.net/librarys/veda/detail/2576 故事还得从头说起,最初的主角叫NCSA Mosaic,简称Mosaic(马赛克) ...