ABP入门系列(15)——创建微信公众号模块

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包,点击确定安装即可。

安装Abp需要依赖安装的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包。

安装Abp.Web.Api需要依赖安装的Nuget包

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

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

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

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

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

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

3. ABP模块化设计

说到模块,突然想到几个单词考考大家,model、modal、module分别是什么意思?
不知道的就自行查词典吧。

下面回归正题。

3.1. 模块化相关类型

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

Module相关类型依赖图

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

  • 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动态加载的调用堆栈。

Module动态加载的调用堆栈

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

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

好了模块的启动加载就讲到这里,感兴趣的还是建议大家直接看看源码。
这里推荐一篇文章ABP源码分析三:ABP Module,来帮助大家理解Abp的模块化思想。

4. 总结

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,449评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,733评论 6 342
  • 你都如何回忆我, 带着笑, 或是, 很沉默。 --刘若英《后来》
    曰旧白阅读 188评论 0 0
  • 6月18日有幸听了一场李善友教授的演讲盛宴,不是第一次听闻第一性原理,却是第一次感到震撼。 李善友教授开篇讲第一性...
    杨杨xx阅读 2,252评论 2 9
  • 初入这个行业,在工作中遇到了疑惑,便在网上翻译了一篇歪果仁写的文章:《为什么通向优秀的设计的设计之路要承认你是错的...
    粒粒阅读 451评论 0 3