本文首发于个人博客(https://blog.zhangchi.fun/)

在进行框架的选型时,经常会听到“***框架太重了”之类的声音,比如“Abp太重了,不适合我们...”。事实上,Abp框架真的很重吗?

框架的“轻”和“重”,我没有在网上找到明确的定义,通过阅读一些技术博客,大致可以把框架的“轻”和“重”通过以下几个方面进行区分:

  • 所依赖程序集的数量

  • 所实现的功能的多少

  • 上手难度及易用性

“轻量级”的框架,大概指的是一个程序集依赖少且程序集文件小、功能虽少但足够满足需求、上手容易使用简单的框架;“重量级”的框架,大概指的是一个程序集依赖多且程序集文件大、功能丰富但大多数用不到、上手困难且使用困难的框架。

这篇文章将从上述几个方面来探索Abp是一个“轻量级”还是“重量级”的框架。

最小依赖

Abp开发了一些启动模板来为我们生成项目。启动模板采用了领域驱动设计的分层方案来建立项目层级,包括了展示层应用层领域层基础设施层

我们通常都会通过Abp CLI或Abp.io来创建类似上图架构的项目。Abp为我们生成的项目,减少了我们初始化项目的工作量,开箱即用,因此将我们可能会使用的Nuget包预先引入到我们的项目中,也就给我们一种依赖项太多的感觉。

从架构设计上来讲,模块化是Abp的核心;而从技术角度来看,依赖注入则是Abp实现众多功能的一个主要手段。只要了解Abp的模块化依赖注入,我们就能够基于Abp框架来进行项目开发。

接下来将创建一个原生的ASP.NET Core Web API项目,围绕模块化依赖注入两个核心概念,来展示如何以最小依赖的方式使用Abp。

  • 通过VS或者dotNet cli新建一个原生的ASP.NET Core Web API项目,命名为LightweightAbp

  • 安装Nuget包Volo.Abp.AutofacVolo.Abp.AspNetCore.Mvc

  • 将项目进行模块化:在项目根目录新建一个Abp模块代码文件LightweightAbpModule.cs,并复制以下代码:

[DependsOn(typeof(AbpAutofacModule),typeof(AbpAspNetCoreMvcModule))]
public class LightweightAbpModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){}public override void OnApplicationInitialization(ApplicationInitializationContext context){}
}
  • Startup中的代码调整到LightweightAbpModule中,代码如下:

[DependsOn(typeof(AbpAutofacModule),typeof(AbpAspNetCoreMvcModule))]
public class LightweightAbpModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){context.Services.AddControllers();context.Services.AddSwaggerGen(c =>{c.SwaggerDoc("v1", new OpenApiInfo { Title = "LightweightAbp", Version = "v1" });});}public override void OnApplicationInitialization(ApplicationInitializationContext context){var app = context.GetApplicationBuilder();var env = context.GetEnvironment();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "LightweightAbp v1"));}app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}
}
  • 更改Startup中的代码以使用Abp的模块化系统:

public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddApplication<LightweightAbpModule>();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory){app.InitializeApplication();}
}
  • 更改ProgramCreateHostBuilder方法以使用Abp的依赖注入系统(基于Autofac):

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).UseAutofac();
  • 将项目生成的WeatherForecastController基类ControllerBase更改为AbpController

  • F5运行。

至此项目的创建完成了。可以看到,仅仅依赖了Volo.Abp.AutofacVolo.Abp.AspNetCore.Mvc两个Nuget包,即可利用Abp进行开发。若从所依赖Nuget包数量来评估框架的“轻”和“重”,那么Abp不可谓不轻。

功能按需使用

得益于模块化设计,Abp将其所能提供的功能,划分并封装到了不同的模块中。要想使用Abp提供的某一功能,只需引入相关的Nuget包并依赖(DependsOn)模块即可。

数据访问

要想实现数据访问功能,首先我们需要定义EntityDbContext并配置数据库支持。在Abp的层次架构中,EntityRepository属于领域层,Service属于应用层,DbContext则属于EntityFramework Core模块,因此我们按需引入所需模块即可。

  • 安装Nuget包Volo.Abp.Ddd.ApplicationVolo.Abp.Ddd.DomainVolo.Abp.EntityFrameworkCore.Sqlite

  • LightweightAbpModule类中配置DependsOn特性,将AbpDddApplicationModuleAbpDddDomainModuleAbpEntityFrameworkCoreSqliteModule模块依赖到我们的项目模块中。

    [DependsOn(typeof(AbpAutofacModule),typeof(AbpAspNetCoreMvcModule),typeof(AbpDddApplicationModule),typeof(AbpDddDomainModule),typeof(AbpEntityFrameworkCoreSqliteModule))]public class LightweightAbpModule : AbpModule{ ... }
  • 然后创建实体Book及数据库上下文LightweightAbpDbContext:

using System;
using Volo.Abp.Domain.Entities;namespace LightweightAbp
{public class Book : Entity<Guid>{public string Name { get; set; }}
}
[ConnectionStringName("Default")]
public class LightweightAbpDbContext : AbpDbContext<LightweightAbpDbContext>
{public LightweightAbpDbContext(DbContextOptions<LightweightAbpDbContext> options): base(options){ }public DbSet<Book> Books { get; set; }protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(builder);builder.Entity<Book>(b =>{b.ToTable(nameof(Books));});}
}
  • LightweightAbpModuleConfigureServices方法中配置数据库访问:

public override void ConfigureServices(ServiceConfigurationContext context)
{...context.Services.AddAbpDbContext<LightweightAbpDbContext>(options =>{options.AddDefaultRepositories(includeAllEntities: true);});Configure<AbpDbContextOptions>(options =>{options.UseSqlite();});
}
  • appsettings.json中配置数据库连接字符串

{..."ConnectionStrings": {"Default": "Data Source=LightweightAbp.db"}
}
  • 安装Nuget包"Microsoft.EntityFrameworkCore.Tools",并在在项目根目录下打开命令行工具,依次执行以下命令进行数据迁移和数据库更新:

dotnet ef migrations add InitialCreate
dotnet ef database update
  • 创建IBookAppServiceBookAppService:

public interface IBookAppService
{Task CreateAsync(string name);
}
public class BookAppService : ApplicationService, IBookAppService
{public IRepository<Book, Guid> Repository => LazyServiceProvider.LazyGetRequiredService<IRepository<Book, Guid>>();public async Task<string> CreateAsync(string name){var book = await Repository.InsertAsync(new Book(){Name = name});return book.Name;}
}
  • 在文件夹Controllers中创建BookController:

[ApiController]
[Route("[controller]")]
public class BookController : AbpController
{private readonly IBookAppService _service;public BookController(IBookAppService service){_service = service;}[HttpGet]public Task<string> CreateAsync(string name){return _service.CreateAsync(name);}
}
  • F5以调试模式运行即可在Swagger页面上插入数据:

这里我们实现了简单的数据插入。可以看到,项目中并没有使用复杂架构和复杂的领域驱动设计,仅引用并配置Abp模块,即可使用常规的 ASP.NET Core Web API方式进行开发。

缓存

接下来我们将继续实现缓存功能。

  • 引用Nuget包Volo.Abp.Caching并向LightweightAbpModule添加AbpCachingModule模块依赖;

  • 修改IBookAppServiceBookAppService实现GetAllAsync方法:

public interface IBookAppService
{Task<string> CreateAsync(string name);Task<string[]> GetAllAsync();
}
public class BookAppService : ApplicationService, IBookAppService
{private readonly IRepository<Book, Guid> _repository;private readonly IDistributedCache<string[]> _cache;public BookAppService(IRepository<Book, Guid> repository,IDistributedCache<string[]> cache){_repository = repository;_cache = cache;}public async Task<string> CreateAsync(string name){ ... }public async Task<string[]> GetAllAsync(){return await _cache.GetOrAddAsync("AllBooksName",async () => await _repository.Select(b => b.Name).ToArrayAsync(),() => new DistributedCacheEntryOptions{AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)});}
}
  • 修改BookAppService实现GetAllAsyncAPI接口:

public class BookController : AbpController
{...[HttpGet("all")]public Task<string[]> GetAllAsync(){return _service.GetAllAsync();}
}
  • F5以调试方式运行,即可调用实现了缓存功能的GetAllAsync接口。

这里我们实现了缓存功能。显而易见,按需使用缓存功能所在的Nuget包及模块即可,并没有很多繁杂的操作。

众所周知,Abp实现了相当多的功能,其中有些功能也许整个项目生命周期中都不会用到。得益于模块化的方式,我们可以只依赖我所需要的Nuget包和Abp模块。如果根据功能多少来评判框架的“轻”和“重”,我们按需依赖不同模块时Abp框架不可谓不轻。由此可见,一个框架的“轻”和“重”,有时还会取决于使用方式。

上手难度及易用性

学习一门新技术最好的起点便是官方文档,Abp也是如此,Abp的官方文档非常详尽介绍了各个功能。Abp还为我们提供了启动模板,模板遵循了领域驱动设计的最佳实践来进行项目分层,并且为我们继承了很多项目中常用的功能模块。

对于初学者而言,面对一个复杂的分层架构及丰富的功能特性支持,一瞬间需要接受非常多的知识,因此会产生无从下手的感觉,进而得出一种上手难度高,框架很“重”的结论。

如果从另外一种角度来学习Abp的话,也许情况会有所不同。在本文之初,我便提出了Abp的核心是模块化依赖注入的观点,当我们将入门的重点放在模块化依赖注入上,那么会发现Abp是一个极易上手并且学习曲线很平缓的框架。正如上文我所进行的代码演示,如果感觉这个演示项目简单易学,那么就证明了我这一观点。

至于易用性,首先Abp实现的功能很全面,我们可以按需使用;其次,随着对Abp框架的逐步深入,会发现模块化的设计让我们的项目集成多种功能变得简单,并且随着项目的演进,Abp的模块化给我们提供了轻易切换到微服务方案的能力;依赖注入系统让我们能够轻易的定制并替换Abp默认实现的功能。因此,我认为Abp是一个易于使用的框架。

总结

在这里我们从一个不同的角度来认识了Abp框架,显而易见,对于Abp来讲,是否太“重”,和我们对他的认知及使用方式有很大的关联。

项目示例代码将托管在Github中。

致谢

感谢Abp群(QQ群:48039003)的群友们提供的热心帮助。

Abp太重了?轻量化Abp框架相关推荐

  1. 轻量化前端框架与小程序移动开发

    小程序是一种运行在移动端的应用形式,它可以提供快速.便捷.丰富的用户体验.但小程序的开发需要遵循一套特定的规范和接口,这对于前端开发者来说可能会有一定的学习成本和限制. 为了简化小程序的开发流程和提高 ...

  2. 深度学习与计算机视觉教程(10) | 轻量化CNN架构 (SqueezeNet,ShuffleNet,MobileNet等)(CV通关指南·完结)

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/37 本文地址:https://www.showmeai.tech/article-d ...

  3. ABP前端使用阿里云angular2 UI框架NG-ZORRO分享

    一.前言 前段时间写博客分享和介绍了阿里云的UI框架NG-ZORRO(博客请查看:http://www.cnblogs.com/donaldtdz/p/7892960.html),结合近段时间对.Ne ...

  4. Pico.css大道至简返璞归真--一个简单轻量化的CSS框架

    Pico.css是什么? Pico.css是一个简单轻量化的CSS UI框架,最大的特点是样式都基于HTML原始的标签名和内置的属性,少用甚至是不用class来定义样式,写出来的代码语义清晰,可维护性 ...

  5. 打造淘宝极简包的轻量化框架

    淘宝极简包项目分离了一个可以快速搭建极简App的框架. 如今app冗余与包大小一直都是很多业务挥之不去的优化项.行业内很多极简包如雨后春笋般冒出来.又或者是很多业务对极简包的探索也有积极的尝试. 极简 ...

  6. 56 Marvin: 一个支持GPU加速、且不依赖其他库(除cuda和cudnn)的轻量化多维深度学习(deep learning)框架介绍...

    0 引言 Marvin是普林斯顿视觉实验室(PrincetonVision)于2015年提出的轻量化GPU加速的多维深度学习网络框架.该框架采用纯c/c++编写,除了cuda和cudnn以外,不依赖其 ...

  7. abp项目怎样发布到服务器,ABP框架的基础配置及依赖注入讲解

    配置ABP 配置是通过在自己模块的PreInitialize方法中来实现的 代码示例如下: ? 和orchard类似,abp框架一开始就被设计成模块化的,不同的模块可以通过abp框架来进行配置.举个例 ...

  8. 输入一个性别、身高和体重值,输出其形体状态(太轻、标准、太重)

    输入一个性别.身高和体重值,输出其形体状态(太轻.标准.太重). 男性标准体重值(kg)= 身高>=165cm:身高(cm)-100 身高<165cm:身高(cm)-105 女性标准体重值 ...

  9. ABP 详解系列2:解析ABP框架中的数据传输对象与应用服务

    解析ABP框架中的数据传输对象与应用服务 ABP框架是基于ASP.NET的Web开发框架,在ABP中应用服务将领域逻辑暴露给展现层,展现层通过传入数据传输对象参数来调用应用服务,而这里我们就来解析AB ...

最新文章

  1. R语言dist函数距离计算实战(欧几里得距离、曼哈顿距离)
  2. 分组密码的工作模式--wiki
  3. [error]Cannot create __weak reference in file using manual refer XCode7.3
  4. SwiftUI优秀文章经典案例制作简易的新闻列表Demo
  5. 阿里云推出全新内存增强型实例re6,性能提升30%
  6. python中pip已经安装好第三方库,但在pycharm中import时还是标红
  7. win10如何截屏_win10系统电脑截屏的多种操作方法
  8. AspectJ注解版和XML版
  9. Redmi K40 Pro渲染图曝光:后置相机模组成最大焦点
  10. 探索安卓中有意义的动画!
  11. 文本圆角背景_ppt模板航天日PPT,半透明几何圆角长方形文本框
  12. Android小项目合集(经典教程)包含十五个Android开发应用实例
  13. 计算机在施工中的应用研究,浅析计算机技术及网络在工程施工中的应用研究.pdf...
  14. C++ 常用的八种排序方法
  15. 梯度消失和梯度爆炸原因推导
  16. 删除桌面上的天猫双十一图标
  17. TYPE-C HUB(拓展坞)乐得瑞LDR6023A快充方案介绍
  18. Java中带有T Z格式(UTC是世界标准时间)的时间转换为date,string,long类型
  19. 电气系统中防雷接地保护的综合解决方案
  20. 06_03_SpringMVC 任务一: SpringMVC基本应用(SpringMVC请求与响应,进行日期转换工具类DateConverter)

热门文章

  1. 第二天:装饰模式及面向对象设计原则4则
  2. oracle 创建自增列及其oracle表的字段的子节点的查询
  3. [music]Canon and Gigue in D major
  4. decode 大于比较 小于_6 燃气输配系统6.3 压力不大于1.6Mpa的室外燃气管道城镇燃气设计规范 GB500282006(2020修订版)...
  5. 腾讯的一笔画游戏--巧妙解法
  6. hdu - 2586 How far away ?(最短路共同祖先问题)
  7. android 局域网邻居,局域网内无邻居 它们去哪儿了?
  8. 记一次理想浪漫的毕旅
  9. dvd vlc 复制_如何使用VLC翻录DVD
  10. 美国用户现在可以下载其所有Apple帐户数据,这是操作方法