当前位置: 首页 > 编程日记 > 正文

ABP中的Filter(下)

接着上面的一个部分来叙述,这一篇我们来重点看ABP中的AbpUowActionFilter、AbpExceptionFilter、AbpResultFilter这三个部分也是按照之前的思路来一个个介绍,当然这里面如果和前面的Interceptor有重复的部分,那么将会对两者进行一个对比并作出相关的说明,那么我们现在来一步步来分析这几个Filter的细节。

 四   AbpUowActionFilter

  这个我们需要和之前的UnitOfWorkInterceptor中的上篇下篇来进行对比,工作单元部分是整个ABP中非常重要的一个部分,这里我们也来简要的进行分析,详细的过程可以参考UnitOfWorkInterceptor中的过程来说明,这里主要是说一下两者的不同之处,这里我们先看看这部分的代码,然后再进行分析。

public class AbpUowActionFilter : IAsyncActionFilter, ITransientDependency{private readonly IUnitOfWorkManager _unitOfWorkManager;private readonly IAbpAspNetCoreConfiguration _aspnetCoreConfiguration;private readonly IUnitOfWorkDefaultOptions _unitOfWorkDefaultOptions;public AbpUowActionFilter(IUnitOfWorkManager unitOfWorkManager,IAbpAspNetCoreConfiguration aspnetCoreConfiguration,IUnitOfWorkDefaultOptions unitOfWorkDefaultOptions){_unitOfWorkManager = unitOfWorkManager;_aspnetCoreConfiguration = aspnetCoreConfiguration;_unitOfWorkDefaultOptions = unitOfWorkDefaultOptions;}public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){if (!context.ActionDescriptor.IsControllerAction()){await next();return;}var unitOfWorkAttr = _unitOfWorkDefaultOptions.GetUnitOfWorkAttributeOrNull(context.ActionDescriptor.GetMethodInfo()) ??_aspnetCoreConfiguration.DefaultUnitOfWorkAttribute;if (unitOfWorkAttr.IsDisabled){await next();return;}using (var uow = _unitOfWorkManager.Begin(unitOfWorkAttr.CreateOptions())){var result = await next();if (result.Exception == null || result.ExceptionHandled){await uow.CompleteAsync();}}}}

这里我们来一步步进行分析,首先第一步也是判断当前执行的方法是否是ControllerAction,确确来说就是当前执行的方法是否位于Controller的内部,如果当前方法不是ControllerAction的话那么就不再拦截当前方法,这个和前面分析的是一样的。然后第二部就是通过下面的GetUnitOfWorkAttributeOrNull这个方法来判断能够进行后续操作。

 internal static class UnitOfWorkDefaultOptionsExtensions{public static UnitOfWorkAttribute GetUnitOfWorkAttributeOrNull(this IUnitOfWorkDefaultOptions unitOfWorkDefaultOptions, MethodInfo methodInfo){var attrs = methodInfo.GetCustomAttributes(true).OfType<UnitOfWorkAttribute>().ToArray();if (attrs.Length > 0){return attrs[0];}attrs = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true).OfType<UnitOfWorkAttribute>().ToArray();if (attrs.Length > 0){return attrs[0];}if (unitOfWorkDefaultOptions.IsConventionalUowClass(methodInfo.DeclaringType)){return new UnitOfWorkAttribute(); //Default}return null;}public static bool IsConventionalUowClass(this IUnitOfWorkDefaultOptions unitOfWorkDefaultOptions, Type type){return unitOfWorkDefaultOptions.ConventionalUowSelectors.Any(selector => selector(type));}}

这是一个扩展方法,主要是获取当前方法的名称为UnitOfWork的自定义属性,当然这个【UnitOfWork】可以定义在当前方法的上面,当然也可以定义在该方法的类的上面,如果定义在类的上面则表示整个类都拥有UnitOfWork特性。另外我们可以定义我们自己的规则,从而确保当前方法能够运用到UnitOfWork的特性,具体的方法就是在UnitOfWorkDefaultOptions中定义自己的ConventionalUowSelectors,我们来看看UnitOfWorkDefaultOptions的实现。

internal class UnitOfWorkDefaultOptions : IUnitOfWorkDefaultOptions{public TransactionScopeOption Scope { get; set; }/// <inheritdoc/>public bool IsTransactional { get; set; }/// <inheritdoc/>public TimeSpan? Timeout { get; set; }/// <inheritdoc/>public bool IsTransactionScopeAvailable { get; set; }/// <inheritdoc/>public IsolationLevel? IsolationLevel { get; set; }public IReadOnlyList<DataFilterConfiguration> Filters => _filters;private readonly List<DataFilterConfiguration> _filters;public List<Func<Type, bool>> ConventionalUowSelectors { get; }public UnitOfWorkDefaultOptions(){_filters = new List<DataFilterConfiguration>();IsTransactional = true;Scope = TransactionScopeOption.Required;IsTransactionScopeAvailable = true;ConventionalUowSelectors = new List<Func<Type, bool>>{type => typeof(IRepository).IsAssignableFrom(type) ||typeof(IApplicationService).IsAssignableFrom(type)};}public void RegisterFilter(string filterName, bool isEnabledByDefault){if (_filters.Any(f => f.FilterName == filterName)){throw new AbpException("There is already a filter with name: " + filterName);}_filters.Add(new DataFilterConfiguration(filterName, isEnabledByDefault));}public void OverrideFilter(string filterName, bool isEnabledByDefault){_filters.RemoveAll(f => f.FilterName == filterName);_filters.Add(new DataFilterConfiguration(filterName, isEnabledByDefault));}}

在这个里面有一个公共的名称为ConventionalUowSelectors的Func委托集合,在这个里面我们默认添加了从IRepository或者IApplicationService的类型自动添加UnitOfWork的特性的方式,当然我们也可以在我们的Module里面添加自己的UowSelector,通过上面的代码我们可以了解整个过程,在获取了当前的方法的UnitOfWorkAttribute后我们需要判断当前的IsDisable是否为true,如果为true那么再次跳过UnitOfWork的过程,最后就是通过UnitOfWorkManager来启动工作单元,其内部具体的执行过程请参考UnitOfWorkInterceptor中详细的过程。

  五   AbpExceptionFilter

这个应该在ABP中非常常见的一类Filter,在我们的代码中底层抛出异常之后我们到底该怎么处理呢?我们来看看ABP中写了哪些?处理过程又是什么样的?

 public class AbpExceptionFilter : IExceptionFilter, ITransientDependency{public ILogger Logger { get; set; }public IEventBus EventBus { get; set; }private readonly IErrorInfoBuilder _errorInfoBuilder;private readonly IAbpAspNetCoreConfiguration _configuration;public AbpExceptionFilter(IErrorInfoBuilder errorInfoBuilder, IAbpAspNetCoreConfiguration configuration){_errorInfoBuilder = errorInfoBuilder;_configuration = configuration;Logger = NullLogger.Instance;EventBus = NullEventBus.Instance;}public void OnException(ExceptionContext context){if (!context.ActionDescriptor.IsControllerAction()){return;}var wrapResultAttribute =ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(context.ActionDescriptor.GetMethodInfo(),_configuration.DefaultWrapResultAttribute);if (wrapResultAttribute.LogError){LogHelper.LogException(Logger, context.Exception);}if (wrapResultAttribute.WrapOnError){HandleAndWrapException(context);}}private void HandleAndWrapException(ExceptionContext context){if (!ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType)){return;}context.HttpContext.Response.StatusCode = GetStatusCode(context);context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(context.Exception),context.Exception is AbpAuthorizationException));EventBus.Trigger(this, new AbpHandledExceptionData(context.Exception));context.Exception = null; //Handled!}protected virtual int GetStatusCode(ExceptionContext context){if (context.Exception is AbpAuthorizationException){return context.HttpContext.User.Identity.IsAuthenticated? (int)HttpStatusCode.Forbidden: (int)HttpStatusCode.Unauthorized;}if (context.Exception is AbpValidationException){return (int)HttpStatusCode.BadRequest;}if (context.Exception is EntityNotFoundException){return (int)HttpStatusCode.NotFound;}return (int)HttpStatusCode.InternalServerError;}}

在这个方法中,首先也是过滤ControllerAction,然后就会获取当前执行方法或者其所属的类上面是否定义了WrapResultAttribute,如果找不到自定义的WrapResultAttribute,那么会为其添加一个默认的WrapResultAttribute,默认的WrapResultAttribute中默认定义LogError=true,所以默认会通过LogHelper.LogException(Logger, context.Exception)来记录当前系统中异常信息作为日志文件。当然这里我们也可以看看HandleAndWrapException中到底做了些什么?

首先是判断当前的方法的返回值是否是一个ObjectResult,那么到底什么是ObjectResult,我们一起来看看。

 public static bool IsObjectResult(Type returnType){//Get the actual return type (unwrap Task)if (returnType == typeof(Task)){returnType = typeof(void);}else if (returnType.GetTypeInfo().IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)){returnType = returnType.GenericTypeArguments[0];}if (typeof(IActionResult).GetTypeInfo().IsAssignableFrom(returnType)){if (typeof(JsonResult).GetTypeInfo().IsAssignableFrom(returnType) || typeof(ObjectResult).GetTypeInfo().IsAssignableFrom(returnType)){return true;}return false;}return true;}

首先来判断当前方法的返回值是否继承自IActionResult,在满足这个条件以后再来看当前方法的返回值是否继承自JsonResult或者是ObjectResult,如果是那么就返回true。返回true后我们会获取当前Response的状态码并且以AjaxRespone的形式返回。这里我们看看在实际的业务中我们的处理方式,看下面的代码。

 /// <summary>/// API 的未捕捉异常处理/// </summary>public class ApiExceptionFilter : IExceptionFilter {/// <summary>/// 仅针对 /api/ 开头的 HTTP API 处理异常/// </summary>/// <param name="context">异常的上下文</param>public void OnException(ExceptionContext context) {var route = context.ActionDescriptor.AttributeRouteInfo.Template;if (route.StartsWith("api/")) {HandleException(context);}}/// <summary>/// 针对不同的异常,HTTP Response 使用不同的 Status Code, Body 均定义为 { "message": "exception message" }/// </summary>/// <param name="context"></param>private void HandleException(ExceptionContext context) {context.HttpContext.Response.StatusCode = GetStatusCode(context);if (context.Exception is AbpValidationException exception) {context.Result = new ObjectResult(new {// Message = "你的请求无效",ValidationErrors = GetValidationErrorInfos(exception),Message = GetValidationErrorNarrative(exception)});} else if (context.Exception is FileValidationException fileValidationException) {context.Result = new ObjectResult(new {payload = fileValidationException.FileName,fileValidationException.Message});} else {var message = context.Exception.Message;if (context.Exception.InnerException is ValidationException)message = context.Exception.InnerException.Message;context.Result = new ObjectResult(new {Message = message});}context.ExceptionHandled = true;}private int GetStatusCode(ExceptionContext context) {if (context.Exception is AbpAuthorizationException) {return context.HttpContext.User.Identity.IsAuthenticated? StatusCodes.Status403Forbidden: StatusCodes.Status401Unauthorized;}if (context.Exception is AbpValidationException|| context.Exception is UserFriendlyException|| context.Exception is ValidationException|| context.Exception is FileValidationException|| context.Exception.InnerException is ValidationException) {return StatusCodes.Status400BadRequest;}if (context.Exception is EntityNotFoundException) {return StatusCodes.Status404NotFound;}if (context.Exception is PreconditionRequiredException) {return StatusCodes.Status428PreconditionRequired;}if (context.Exception is PreconditionFailedException) {return StatusCodes.Status412PreconditionFailed;}return StatusCodes.Status500InternalServerError;}private ValidationErrorInfo[] GetValidationErrorInfos(AbpValidationException validationException) {var validationErrorInfos = new List<ValidationErrorInfo>();foreach (var validationResult in validationException.ValidationErrors) {var validationError = new ValidationErrorInfo(validationResult.ErrorMessage);if (validationResult.MemberNames != null && validationResult.MemberNames.Any()) {validationError.Members = validationResult.MemberNames.Select(m => m.ToCamelCase()).ToArray();}validationErrorInfos.Add(validationError);}return validationErrorInfos.ToArray();}private string GetValidationErrorNarrative(AbpValidationException validationException) {var detailBuilder = new StringBuilder();detailBuilder.AppendLine("验证过程中检测到以下错误");foreach (var validationResult in validationException.ValidationErrors) {detailBuilder.AppendFormat(" - {0}", validationResult.ErrorMessage);detailBuilder.AppendLine();}return detailBuilder.ToString();}}

在实际的业务过程中我们会将当前的报错信息已一定的结构返回给调用的前端,让前端去处理具体的异常信息,通常会将错误信息显示在界面上方几秒中,然后退出的方式。

 六   AbpResultFilter

  这个在实际过程中用的不是很多我们也来看看到底会做些什么吧?

 public class AbpResultFilter : IResultFilter, ITransientDependency{private readonly IAbpAspNetCoreConfiguration _configuration;private readonly IAbpActionResultWrapperFactory _actionResultWrapperFactory;public AbpResultFilter(IAbpAspNetCoreConfiguration configuration, IAbpActionResultWrapperFactory actionResultWrapper){_configuration = configuration;_actionResultWrapperFactory = actionResultWrapper;}public virtual void OnResultExecuting(ResultExecutingContext context){if (!context.ActionDescriptor.IsControllerAction()){return;}var methodInfo = context.ActionDescriptor.GetMethodInfo();//var clientCacheAttribute = ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(//    methodInfo,//    _configuration.DefaultClientCacheAttribute//);//clientCacheAttribute?.Apply(context);var wrapResultAttribute =ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(methodInfo,_configuration.DefaultWrapResultAttribute);if (!wrapResultAttribute.WrapOnSuccess){return;}_actionResultWrapperFactory.CreateFor(context).Wrap(context);}public virtual void OnResultExecuted(ResultExecutedContext context){//no action}}

这个里面最重要就是最后一个Wrap方法,这个方法会根据返回的结果是JsonResult还是ObjectResult来做不同的处理,这里我以ObjectResult为例来进行说明。

 public class AbpObjectActionResultWrapper : IAbpActionResultWrapper{private readonly IServiceProvider _serviceProvider;public AbpObjectActionResultWrapper(IServiceProvider serviceProvider){_serviceProvider = serviceProvider;}public void Wrap(ResultExecutingContext actionResult){var objectResult = actionResult.Result as ObjectResult;if (objectResult == null){throw new ArgumentException($"{nameof(actionResult)} should be ObjectResult!");}if (!(objectResult.Value is AjaxResponseBase)){objectResult.Value = new AjaxResponse(objectResult.Value);if (!objectResult.Formatters.Any(f => f is JsonOutputFormatter)){objectResult.Formatters.Add(new JsonOutputFormatter(_serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value.SerializerSettings,_serviceProvider.GetRequiredService<ArrayPool<char>>()));}}}}

这里面也比较简单就是将最终的结果以Json的格式进行输出。

最后,点击这里返回整个ABP系列的主目录。

转载于:https://www.cnblogs.com/seekdream/p/10490267.html

相关文章:

LRU算法 -- 链表 完整实现

LRU算法(Least Recently Used) 算是我们经常遇到的一种淘汰算法&#xff0c;其中内存管理模块进行内存页回收时有用到&#xff0c;针对不经常使用的内存页&#xff0c;LRU淘汰策略能够将该内存页回收给操作系统。 属于 我们操作系统设计中的 时间局部性原理&#xff0c;最长时…

python getostime_python中sys,os,time模块的使用(包括时间格式的各种转换)

sys模块sys.argv: 实现从程序外部向程序传递参数。位置参数argv[0]代表py文件本身&#xff0c;运行方法 python xx.py 参数1&#xff0c;参数2 。。self sys.argv[0]name sys.argv[1]age sys.argv[2]print self, name, agesys.getdefaultencoding(): 获取系统当前编码&#…

关于SpringMVC和Struts2的区别

1. 与struts2不同 1、 springmvc的入口是一个servlet即前端控制器&#xff0c;而struts2入口是一个filter过虑器。 2、 springmvc是基于方法开发&#xff0c;传递参数是通过方法形参&#xff0c;可以设计为单例或多例(建议单例)&#xff0c;struts2是基于类开发&#xff0c…

DC-RC加固修补型砂浆

DC-RC加固修补型砂浆www.hrbjg.net一、DC-RC加固修补型砂浆的产品特点&#xff1a;1、耐火、耐高温、耐腐蚀、耐老化性能优良。2、强度高&#xff0c;抹灰操作性好。3、与原混凝土结构的粘结性能良好。4、无收缩&#xff0c;基本不会产生裂缝。5、二氧化碳、氯化物等透过性差&a…

类,实例,属性习题

class Restaurant(): def __init__(self,restaurant_name,cuisine_type): self.restaurant_namerestaurant_name self.cuisine_typecuisine_type def describle_restaurant(self): print("打印的第一条消息") print("打印的第…

数据结构和算法 -- 学习导图

数据结构和算法 是作为程序员写出高效代码的基础&#xff0c;为了今后的两年在高效代码之路上持续精进&#xff0c;将按照此学习导图进行 算法和数据结构的刻意练习&#xff0c;同时也希望为同样有高效代码追求的伙伴们提供一条学习路径&#xff0c;共同进步。 以下为今后持续…

HDU 1248 寒冰王座(全然背包:入门题)

HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,仅仅有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑士:"我要买…

java 彩票系统_JAVA版彩票随机生成系统

import java.io.*;import java.util.Random;class num{public static void main(String[]args){//声明一个随机数组int sjsh[]new int[7];int sum;try{InputStreamReader anew InputStreamReader(System.in);BufferedReader bnew BufferedReader(a);System.out.println ("…

Windows Server 2012 文件服务器群集

概述&#xff1a;之前已经测试了Windows Server 2012系统群集、Hyper-V群集&#xff0c;接下来将测试Windows Server 2012 文件服务器群集功能。实验环境&#xff1a;4台服务器都为Windows Server 2012 DataCenter操作系统在之前配置了群集的基础上&#xff0c;SRV2012服务器新…

023 判断出栈顺序是否正确

1.题目 输入两个整数序列&#xff0c;第一个序列表示栈的压入顺序&#xff0c;请判断第二个序列是否为该栈的弹出顺序。 假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列&#xff0c;序列4、5、3、2、1是该压栈序列对应的一个弹出序列&#xff0c;但4、3…

栈 -- 顺序栈、链式栈的实现 及其应用(函数栈,表达式求值,括号匹配)

文章目录实现顺序栈实现链式栈实现应用函数栈 的应用表达式求值中 的应用括号匹配中 的应用我们使用浏览器的时候经常会用到前进、后退功能。依次访问完一串页面 a – b – c之后点击后退功能&#xff0c;则能够依次看到c – b – a的页面。但是这个过程中&#xff0c;如果后退…

OC中的NSArray和NSMutableArray、NSDictionary和NSMutableDictionary用法

一&#xff1a;NSArray 和NSMutableArray1: NSArray&#xff1a;不可变数组NSArray是OC中使用的数组&#xff0c;只能用来存放OC对象&#xff0c;不能存放非OC对象如基本数据类型它使不可变的&#xff0c;一旦初始化完毕&#xff0c;内容不能改变&#xff0c;也不能添加元素。而…

java中ContentArea_java中TextArea怎么加载指定路径的文本内容

展开全部这设计到IO操作&#xff0c;很62616964757a686964616fe58685e5aeb931333332643334久以前练手写的加载文本到文本域的界面。具体代码第一步&#xff1a;得到一个File对象&#xff0c;需要参数文本路径File file new File("C:\\test.txt");第二步&#xff1a;…

文本分类技术基础

分类体系 分类&#xff1a;给定一个对象&#xff0c;从一个事先定义好的分类体系中挑出一个或多个最适合该对象的类别。 文本分类(TC, Text Categorization)&#xff1a;在给定的分类体系下&#xff0c;根据文本内容自动的确定文本关联的类别。从数学角度看&#xff0c;文本分类…

C# 返回值为 listT

public List<T> test<T>(List<T> EntityList) where T : class{return EntityList;} 转载于:https://www.cnblogs.com/enych/p/10497312.html

ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析

文章目录内存查看内存控制内存控制源码分析通过gperftools接口获取osd进程实际内存 动态设置cache大小动态调整cache比例trim释放内存本文通过对ceph-osd内存查看跟踪的5种手段以及osd内存控制的方式进行源码层面的说明&#xff0c;并未通过修改相关源码进行控制&#xff08;水…

c语言函数库学习~sscanf~格式化输入

---恢复内容开始--- 今天算是被打击到了吧&#xff0c;由郑轻的acm老师来我学院指导安排了个现场的小比赛&#xff0c;&#xff0c;俺们居然有还是输给一个大一的新手&#xff0c;&#xff0c;哎&#xff0c;情何以堪&#xff0c;&#xff0c;所以还是要重视下基础编程能力的培…

java mobile phone games_j2me100-src Java

文件名大小更新时间codesc.net\[J2SE]应用编程150例\chap01\实例1\BorderLayoutDemo.class8192003-07-07codesc.net\[J2SE]应用编程150例\chap01\实例1\BorderLayoutDemo.java5752003-07-07codesc.net\[J2SE]应用编程150例\chap01\实例1\BoxLayoutFrame.class7262003-07-15code…

***突然断开可能是ADSL猫惹的祸

在我们使用服务器的时候&#xff0c;最讨厌的就是无故的断线了&#xff0c;可能正在和好一起副本&#xff0c;或者正在视频热聊中&#xff0c;还或者youtube视频看的正起劲&#xff0c;突然windows一个对话框弹出 - “连接已经断开”。实在是太影响体验了&#xff0c;断开之后&…

文件中数组的最大值及其对应的最小下标

2019年春季学期第二周作业基础作业请在第一周作业的基础上&#xff0c;继续完成&#xff1a;找出给定的文件中数组的最大值及其对应的最小下标&#xff08;下标从0开始&#xff09;。并将最大值和对应的最小下标数值写入文件。 输入&#xff1a;请建立以自己英文名字命名的txt文…

ceph bluestore源码分析:admin_socket实时获取内存池数据

环境&#xff1a; 版本&#xff1a;ceph 12.2.1 部署完cephfs 使用ceph-fuse挂载&#xff0c;并写入数据 关键参数&#xff1a; debug_mempool true 将该参数置为true即可查看详细的blustore管理的内存池的数据 命令&#xff1a; ceph daemon osd.id dump_mempools该命令为ad…

java clob内存溢出_java - java.sql.SQLException:ORA-01704:字符串文字太长时插入或更新 - 堆栈内存溢出...

通常&#xff0c;当我插入4000个字符限制时&#xff0c;它的工作正常&#xff0c;但当超过4000个字符时&#xff0c;它抛出SQL异常字符串文字太长&#xff0c;即使我的DISCHARGE_TEXT数据类型是CLOB我的JavaScript代码是function saveAsDraftNew(){var admissionNo document.g…

LC并联谐振回路

转载于:https://www.cnblogs.com/prayer521/p/4103091.html

zencart分类页产品页去掉url中的id号

最近公司新上的网站被seo指出要修改url&#xff0c;去掉url中产品id。由于我们用的是zencart框架&#xff0c;装了 Ultimate SEO URLs 插件&#xff0c;所以在网上应该有这方面的资料&#xff0c;本文主要参考资料&#xff1a;原网址&#xff1a;修改seo url中去掉产品id的方法…

hexo博客更新主题后上传Git操作

克隆主题: git clone https://github.com/SuperKieran/TKL.git _config.yml文件中主题改为新增主题 # Extensions ## Plugins: https://hexo.io/plugins/ ## Themes: https://hexo.io/themes/ theme: TKL 进入主题目录,更新git cd theme/TKL git pull 执行更新 hexo clean hex…

ceph bluestore源码分析:非对齐写逻辑

文章目录环境原理说明总结环境 ceph:12.2.1 场景&#xff1a;ec 21 部署cephfs&#xff0c;执行如右写模式:dd if/dev/zero of/xxx/cephfs bs6K count4 oflagdirect 关键配置&#xff1a; bluestore_min_alloc_size_hdd 65536 bluestore分配空间的最小粒度 单位&#xff1a;B…

JVM系列(之ClassLoader)

Class Loader Java运作流程 内部class loader bootstrap class loader --引导类加载器&#xff0c;它负责加载Java的核心类【java.* 】&#xff08;如classpath下面的类库&#xff09;&#xff0c;不是 java.lang.ClassLoader的子类&#xff0c;而是由JVM自身实现的。Code . UR…

java平台类成员访问修饰符_JAVA类的修饰符及访问权限

1.类外部类 class前的修饰符只能有publicfinalabstrct无(默认) &#xff1a;同包可见 (Eclipse中选择package)内部类 class前的修饰符有public、protected、private、默认、final、abstract、static。先看类的访问权限&#xff0c;再看成员的访问权限&#xff0c;类…

ios实例开发精品源码文章推荐

1、IOS代码分享:视图布局&#xff08;View Layout&#xff09;Border View140601bvpw22rir88b9i8i.png(19.97 KB, 下载次数: 0)下载附件保存到相册半小时前 上传http://www.apkbus.com/android-101999-1-14.html2、IOS代码分享&#xff1a;导航条&#xff08;Navigation Bar&am…

Spring BeanDefinitionRegistryPostProcessor BeanPostProcessor作用

写博客&#xff0c;写博客&#xff0c;把自己知道的小知识点全部记录&#xff0c;? BeanDefinitionRegistryPostProcessor 接口属于Beanddefination 装配定义的范畴&#xff0c;此时bean 并没有初始化 BeanPostProcessor属于be an 实例化修改的范畴&#xff0c;be an 已经进行…