国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Util應(yīng)用框架基礎(chǔ)(三) - 面向切面編程(AspectCore AOP)

這篇具有很好參考價(jià)值的文章主要介紹了Util應(yīng)用框架基礎(chǔ)(三) - 面向切面編程(AspectCore AOP)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本節(jié)介紹Util應(yīng)用框架對(duì)AspectCore AOP的使用.

概述

有些問題需要在系統(tǒng)中全局處理,比如記錄異常錯(cuò)誤日志.

如果在每個(gè)出現(xiàn)問題的地方進(jìn)行處理,不僅費(fèi)力,還可能產(chǎn)生大量冗余代碼,并打斷業(yè)務(wù)邏輯的編寫.

這類跨多個(gè)業(yè)務(wù)模塊的非功能需求,被稱為橫切關(guān)注點(diǎn).

我們需要把橫切關(guān)注點(diǎn)集中管理起來.

Asp.Net Core 提供的過濾器可以處理這類需求.

過濾器有異常過濾器和操作過濾器等類型.

異常過濾器可以全局處理異常.

操作過濾器可以攔截控制器操作,在操作前和操作后執(zhí)行特定代碼.

過濾器很易用,但它必須配合控制器使用,所以只能解決部分問題.

你不能將過濾器特性打在應(yīng)用服務(wù)的方法上,那不會(huì)產(chǎn)生作用.

我們需要引入一種類似 Asp.Net Core 過濾器的機(jī)制,在控制器范圍外處理橫切關(guān)注點(diǎn).

AOP框架

AOP 是 Aspect Oriented Programming 的縮寫,即面向切面編程.

AOP 框架提供了類似 Asp.Net Core 過濾器的功能,能夠攔截方法,在方法執(zhí)行前后插入自定義代碼.

.Net AOP框架有動(dòng)態(tài)代理靜態(tài)織入兩種實(shí)現(xiàn)方式.

動(dòng)態(tài)代理 AOP 框架

動(dòng)態(tài)代理 AOP 框架在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建代理類,從而為方法提供自定義代碼插入點(diǎn).

動(dòng)態(tài)代理 AOP 框架有一些限制.

  • 要攔截的方法必須在接口中定義,或是虛方法.

  • 代理類過多,特別是啟用了參數(shù)攔截,會(huì)導(dǎo)致啟動(dòng)性能下降.

.Net 動(dòng)態(tài)代理 AOP 框架有Castle 和 AspectCore 等.

Util應(yīng)用框架使用 AspectCore ,選擇 AspectCore 是因?yàn)樗右子?

Util 對(duì) AspectCore 僅簡單包裝.

靜態(tài)織入 AOP 框架

靜態(tài)織入 AOP 框架在編譯時(shí)修改.Net IL中間代碼.

與動(dòng)態(tài)代理AOP相比,靜態(tài)織入AOP框架有一些優(yōu)勢.

  • 不必是虛方法.

  • 支持靜態(tài)方法.

  • 更高的啟動(dòng)性能.

但是成熟的 .Net 靜態(tài)織入 AOP 框架大多是收費(fèi)的.

Rougamo.Fody 是一個(gè)免費(fèi)的靜態(tài)織入 AOP 框架,可以關(guān)注.

基礎(chǔ)用法

引用Nuget包

Nuget包名: Util.Aop.AspectCore

啟用Aop

需要明確調(diào)用 AddAop 擴(kuò)展方法啟用 AOP 服務(wù).

var builder = WebApplication.CreateBuilder( args );
builder.AsBuild().AddAop();

使用要點(diǎn)

  • 定義服務(wù)接口

    如果使用抽象基類,應(yīng)將需要攔截的方法設(shè)置為虛方法.

  • 配置服務(wù)接口的依賴注入關(guān)系

    AspectCore AOP依賴Ioc對(duì)象容器,只有在對(duì)象容器中注冊的服務(wù)接口才能創(chuàng)建服務(wù)代理.

  • 將方法攔截器放在接口方法上.

    AspectCore AOP攔截器是一種.Net特性 Attribute,遵循 Attribute 使用約定.

    下面的例子將 CacheAttribute 方法攔截器添加到 ITestService 接口的 Test 方法上.

    注意: 應(yīng)將攔截器放在接口方法上,而不是實(shí)現(xiàn)類上.

    按照約定, CacheAttribute 需要去掉 Attribute 后綴,并放到 [] 中.

    public interface ITestService : ISingletonDependency {        
        [Cache]
        List<string> Test( string value );
    }
    
  • 將參數(shù)攔截器放在接口方法參數(shù)上.

    AspectCore AOP 支持?jǐn)r截特定參數(shù).

    下面的例子在參數(shù) value 上施加了 NotNullAttribute 參數(shù)攔截器.

      public interface ITestService : ISingletonDependency {
          void Test( [NotNull] string value );
      }
    

Util內(nèi)置攔截器

Util應(yīng)用框架使用 Asp.Net Core 過濾器處理全局異常,全局錯(cuò)誤日志,授權(quán)等需求,僅定義少量 AOP 攔截器.

Util應(yīng)用框架定義了幾個(gè)參數(shù)攔截器,用于驗(yàn)證.

  • NotNullAttribute

    • 驗(yàn)證是否為 null,如果為 null 拋出 ArgumentNullException 異常.

    • 使用范例:

      public interface ITestService : ISingletonDependency {
          void Test( [NotNull] string value );
      }
    
  • NotEmptyAttribute

    • 使用 string.IsNullOrWhiteSpace 驗(yàn)證是否為空字符串,如果為空則拋出 ArgumentNullException 異常.

    • 使用范例:

      public interface ITestService : ISingletonDependency {
          void Test( [NotEmpty] string value );
      }
    
  • ValidAttribute

    • 如果對(duì)象實(shí)現(xiàn)了 IValidation 驗(yàn)證接口,則自動(dòng)調(diào)用對(duì)象的 Validate 方法進(jìn)行驗(yàn)證.

      Util應(yīng)用框架實(shí)體,值對(duì)象,DTO等基礎(chǔ)對(duì)象均已實(shí)現(xiàn) IValidation 接口.

    • 使用范例:

      驗(yàn)證單個(gè)對(duì)象.

      public interface ITestService : ISingletonDependency {
          void Test( [Valid] CustomerDto dto );
      }
    

    驗(yàn)證對(duì)象集合.

      public interface ITestService : ISingletonDependency {
          void Test( [Valid] List<CustomerDto> dto );
      }
    

Util應(yīng)用框架為緩存定義了方法攔截器.

  • CacheAttribute

    • 使用范例:
      public interface ITestService : ISingletonDependency {
          [Cache]
          List<string> Test( string value );
      }
    

禁止創(chuàng)建服務(wù)代理

有些時(shí)候,你不希望為某些接口創(chuàng)建代理類.

使用 Util.Aop.IgnoreAttribute 特性標(biāo)記接口即可.

下面演示了從 AspectCore AOP 排除工作單元接口.

[Util.Aop.Ignore]
public interface IUnitOfWork {
    Task<int> CommitAsync();
}

創(chuàng)建自定義攔截器

除了內(nèi)置的攔截器外,你可以根據(jù)需要?jiǎng)?chuàng)建自定義攔截器.

創(chuàng)建方法攔截器

繼承 Util.Aop.InterceptorBase 基類,重寫 Invoke 方法.

下面以緩存攔截器為例講解創(chuàng)建方法攔截器的要點(diǎn).

  • 緩存攔截器獲取 ICache 依賴服務(wù)并創(chuàng)建緩存鍵.

  • 通過緩存鍵和返回類型查找緩存是否存在.

  • 如果緩存已經(jīng)存在,則設(shè)置返回值,不需要執(zhí)行攔截的方法.

  • 如果緩存不存在,執(zhí)行方法獲取返回值并設(shè)置緩存.

Invoke 方法有兩個(gè)參數(shù) AspectContextAspectDelegate.

  • AspectContext上下文提供了方法元數(shù)據(jù)信息和服務(wù)提供程序.

    • 使用 AspectContext 上下文獲取方法元數(shù)據(jù).

      AspectContext 上下文提供了攔截方法相關(guān)的大量元數(shù)據(jù)信息.

      本例使用 context.ServiceMethod.ReturnType 獲取返回類型.

    • 使用 AspectContext 上下文獲取依賴的服務(wù).

      AspectContext上下文提供了 ServiceProvider 服務(wù)提供器,可以使用它獲取依賴服務(wù).

      本例需要獲取緩存操作接口 ICache ,使用 context.ServiceProvider.GetService<ICache>() 獲取依賴.

  • AspectDelegate表示攔截的方法.

    await next( context ); 執(zhí)行攔截方法.

    如果需要在方法執(zhí)行前插入自定義代碼,只需將代碼放在 await next( context ); 之前即可.

/// <summary>
/// 緩存攔截器
/// </summary>
public class CacheAttribute : InterceptorBase {
    /// <summary>
    /// 緩存鍵前綴
    /// </summary>
    public string CacheKeyPrefix { get; set; }
    /// <summary>
    /// 緩存過期間隔,單位:秒,默認(rèn)值:36000
    /// </summary>
    public int Expiration { get; set; } = 36000;

    /// <summary>
    /// 執(zhí)行
    /// </summary>
    public override async Task Invoke( AspectContext context, AspectDelegate next ) {
        var cache = GetCache( context );
        var returnType = GetReturnType( context );
        var key = CreateCacheKey( context );
        var value = await GetCacheValue( cache, returnType, key );
        if ( value != null ) {
            SetReturnValue( context, returnType, value );
            return;
        }
        await next( context );
        await SetCache( context, cache, key );
    }

    /// <summary>
    /// 獲取緩存服務(wù)
    /// </summary>
    protected virtual ICache GetCache( AspectContext context ) {
        return context.ServiceProvider.GetService<ICache>();
    }

    /// <summary>
    /// 獲取返回類型
    /// </summary>
    private Type GetReturnType( AspectContext context ) {
        return context.IsAsync() ? context.ServiceMethod.ReturnType.GetGenericArguments().First() : context.ServiceMethod.ReturnType;
    }

    /// <summary>
    /// 創(chuàng)建緩存鍵
    /// </summary>
    private string CreateCacheKey( AspectContext context ) {
        var keyGenerator = context.ServiceProvider.GetService<ICacheKeyGenerator>();
        return keyGenerator.CreateCacheKey( context.ServiceMethod, context.Parameters, CacheKeyPrefix );
    }

    /// <summary>
    /// 獲取緩存值
    /// </summary>
    private async Task<object> GetCacheValue( ICache cache, Type returnType, string key ) {
        return await cache.GetAsync( key, returnType );
    }

    /// <summary>
    /// 設(shè)置返回值
    /// </summary>
    private void SetReturnValue( AspectContext context, Type returnType, object value ) {
        if ( context.IsAsync() ) {
            context.ReturnValue = typeof( Task ).GetMethods()
                .First( p => p.Name == "FromResult" && p.ContainsGenericParameters )
                .MakeGenericMethod( returnType ).Invoke( null, new[] { value } );
            return;
        }
        context.ReturnValue = value;
    }

    /// <summary>
    /// 設(shè)置緩存
    /// </summary>
    private async Task SetCache( AspectContext context, ICache cache, string key ) {
        var options = new CacheOptions { Expiration = TimeSpan.FromSeconds( Expiration ) };
        var returnValue = context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue;
        await cache.SetAsync( key, returnValue, options );
    }
}

創(chuàng)建參數(shù)攔截器

繼承 Util.Aop.ParameterInterceptorBase 基類,重寫 Invoke 方法.

與方法攔截器類似, Invoke 也提供了兩個(gè)參數(shù) ParameterAspectContext 和 ParameterAspectDelegate.

ParameterAspectContext 上下文提供方法元數(shù)據(jù).

ParameterAspectDelegate 表示攔截的方法.

下面演示了 [NotNull] 參數(shù)攔截器.

在方法執(zhí)行前判斷參數(shù)是否為 null,如果為 null 拋出異常,不會(huì)執(zhí)行攔截方法.

/// <summary>
/// 驗(yàn)證參數(shù)不能為null
/// </summary>
public class NotNullAttribute : ParameterInterceptorBase {
    /// <summary>
    /// 執(zhí)行
    /// </summary>
    public override Task Invoke( ParameterAspectContext context, ParameterAspectDelegate next ) {
        if( context.Parameter.Value == null )
            throw new ArgumentNullException( context.Parameter.Name );
        return next( context );
    }
}

性能優(yōu)化

AddAop 配置方法默認(rèn)不帶參數(shù),所有添加到 Ioc 容器的服務(wù)都會(huì)創(chuàng)建代理類,并啟用參數(shù)攔截器.

AspectCore AOP 參數(shù)攔截器對(duì)啟動(dòng)性能有很大的影響.

默認(rèn)配置適合規(guī)模較小的項(xiàng)目.

當(dāng)你在Ioc容器注冊了上千個(gè)甚至更多的服務(wù)時(shí),啟動(dòng)時(shí)間將顯著增長,因?yàn)閱?dòng)時(shí)需要?jiǎng)?chuàng)建大量的代理類.

有幾個(gè)方法可以優(yōu)化 AspectCore AOP 啟動(dòng)性能.

  • 拆分項(xiàng)目

    對(duì)于微服務(wù)架構(gòu),單個(gè)項(xiàng)目包含的接口應(yīng)該不會(huì)特別多.

    如果發(fā)現(xiàn)由于創(chuàng)建代理類導(dǎo)致啟動(dòng)時(shí)間過長,可以拆分項(xiàng)目.

    但對(duì)于單體架構(gòu),不能通過拆分項(xiàng)目的方式解決.

  • 減少創(chuàng)建的代理類.

    Util定義了一個(gè)AOP標(biāo)記接口 IAopProxy ,只有繼承了 IAopProxy 的接口才會(huì)創(chuàng)建代理類.

    要啟用 IAopProxy 標(biāo)記接口,只需向 AddAop 傳遞 true .

      var builder = WebApplication.CreateBuilder( args );
      builder.AsBuild().AddAop( true );
    

    現(xiàn)在只有明確繼承自 IAopProxy 的接口才會(huì)創(chuàng)建代理類,代理類的數(shù)量將大幅減少.

    應(yīng)用服務(wù)和領(lǐng)域服務(wù)接口默認(rèn)繼承了 IAopProxy.

    如果你在其它構(gòu)造塊使用了攔截器,比如倉儲(chǔ),需要讓你的倉儲(chǔ)接口繼承 IAopProxy.

  • 禁用參數(shù)攔截器.

    如果啟用了 IAopProxy 標(biāo)記接口,啟動(dòng)性能依然未達(dá)到你的要求,可以禁用參數(shù)攔截器.

    AddAop 擴(kuò)展方法支持傳入 Action<IAspectConfiguration> 參數(shù),可以覆蓋默認(rèn)設(shè)置.

    下面的例子禁用了參數(shù)攔截器,并為所有繼承了 IAopProxy 的接口創(chuàng)建代理.

      var builder = WebApplication.CreateBuilder( args );
      builder.AsBuild().AddAop( options => options.NonAspectPredicates.Add( t => !IsProxy( t.DeclaringType ) ) );
    
      /// <summary>
      /// 是否創(chuàng)建代理
      /// </summary>
      private static bool IsProxy( Type type ) {
          if ( type == null )
              return false;
          var interfaces = type.GetInterfaces();
          if ( interfaces == null || interfaces.Length == 0 )
              return false;
          foreach ( var item in interfaces ) {
              if ( item == typeof( IAopProxy ) )
                  return true;
          }
          return false;
      }
    

源碼解析

AppBuilderExtensions

擴(kuò)展了 AddAop 配置方法.

isEnableIAopProxy 參數(shù)用于啟用 IAopProxy 標(biāo)記接口.

Action<IAspectConfiguration> 參數(shù)用于覆蓋默認(rèn)配置.

/// <summary>
/// Aop配置擴(kuò)展
/// </summary>
public static class AppBuilderExtensions {
    /// <summary>
    /// 啟用AspectCore攔截器
    /// </summary>
    /// <param name="builder">應(yīng)用生成器</param>
    public static IAppBuilder AddAop( this IAppBuilder builder ) {
        return builder.AddAop( false );
    }

    /// <summary>
    /// 啟用AspectCore攔截器
    /// </summary>
    /// <param name="builder">應(yīng)用生成器</param>
    /// <param name="isEnableIAopProxy">是否啟用IAopProxy接口標(biāo)記</param>
    public static IAppBuilder AddAop( this IAppBuilder builder,bool isEnableIAopProxy ) {
        return builder.AddAop( null, isEnableIAopProxy );
    }

    /// <summary>
    /// 啟用AspectCore攔截器
    /// </summary>
    /// <param name="builder">應(yīng)用生成器</param>
    /// <param name="setupAction">AspectCore攔截器配置操作</param>
    public static IAppBuilder AddAop( this IAppBuilder builder, Action<IAspectConfiguration> setupAction ) {
        return builder.AddAop( setupAction, false );
    }

    /// <summary>
    /// 啟用AspectCore攔截器
    /// </summary>
    /// <param name="builder">應(yīng)用生成器</param>
    /// <param name="setupAction">AspectCore攔截器配置操作</param>
    /// <param name="isEnableIAopProxy">是否啟用IAopProxy接口標(biāo)記</param>
    private static IAppBuilder AddAop( this IAppBuilder builder, Action<IAspectConfiguration> setupAction, bool isEnableIAopProxy ) {
        builder.CheckNull( nameof( builder ) );
        builder.Host.UseServiceProviderFactory( new DynamicProxyServiceProviderFactory() );
        builder.Host.ConfigureServices( ( context, services ) => {
            ConfigureDynamicProxy( services, setupAction, isEnableIAopProxy );
            RegisterAspectScoped( services );
        } );
        return builder;
    }

    /// <summary>
    /// 配置攔截器
    /// </summary>
    private static void ConfigureDynamicProxy( IServiceCollection services, Action<IAspectConfiguration> setupAction, bool isEnableIAopProxy ) {
        services.ConfigureDynamicProxy( config => {
            if ( setupAction == null ) {
                config.NonAspectPredicates.Add( t => !IsProxy( t.DeclaringType, isEnableIAopProxy ) );
                config.EnableParameterAspect();
                return;
            }
            setupAction.Invoke( config );
        } );
    }

    /// <summary>
    /// 是否創(chuàng)建代理
    /// </summary>
    private static bool IsProxy( Type type, bool isEnableIAopProxy ) {
        if ( type == null )
            return false;
        if ( isEnableIAopProxy == false ) {
            if ( type.SafeString().Contains( "Xunit.DependencyInjection.ITestOutputHelperAccessor" ) )
                return false;
            return true;
        }
        var interfaces = type.GetInterfaces();
        if ( interfaces == null || interfaces.Length == 0 )
            return false;
        foreach ( var item in interfaces ) {
            if ( item == typeof( IAopProxy ) )
                return true;
        }
        return false;
    }

    /// <summary>
    /// 注冊攔截器服務(wù)
    /// </summary>
    private static void RegisterAspectScoped( IServiceCollection services ) {
        services.AddScoped<IAspectScheduler, ScopeAspectScheduler>();
        services.AddScoped<IAspectBuilderFactory, ScopeAspectBuilderFactory>();
        services.AddScoped<IAspectContextFactory, ScopeAspectContextFactory>();
    }
}

Util.Aop.IAopProxy

IAopProxy 是一個(gè)標(biāo)記接口,繼承了它的接口才會(huì)創(chuàng)建代理類.

/// <summary>
/// Aop代理標(biāo)記
/// </summary>
public interface IAopProxy {
}

Util.Aop.InterceptorBase

InterceptorBase 是方法攔截器基類.

它是一個(gè)簡單抽象層, 未來可能提供一些共享方法.

/// <summary>
/// 攔截器基類
/// </summary>
public abstract class InterceptorBase : AbstractInterceptorAttribute {
}

Util.Aop.ParameterInterceptorBase

ParameterInterceptorBase 是參數(shù)攔截器基類.

/// <summary>
/// 參數(shù)攔截器基類
/// </summary>
public abstract class ParameterInterceptorBase : ParameterInterceptorAttribute {
}

Util.Aop.IgnoreAttribute

[Util.Aop.Ignore] 用于禁止創(chuàng)建代理類.文章來源地址http://www.zghlxwxcb.cn/news/detail-743513.html

/// <summary>
/// 忽略攔截
/// </summary>
public class IgnoreAttribute : NonAspectAttribute {
}

到了這里,關(guān)于Util應(yīng)用框架基礎(chǔ)(三) - 面向切面編程(AspectCore AOP)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • AOP(面向切面編程)

    AOP(面向切面編程)

    AOP 又名 Aspect Oriented Programming 意為 ‘面向切面編程’通過預(yù)編譯和運(yùn)行期間動(dòng)態(tài)代理來實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。 AOP 思想是OOP(面向?qū)ο?的延續(xù) 在 OOP 中, 我們以類(class)作為我們的基本單元, 而 AOP 中的基本單元是 Aspect(切面), AOP 是軟件行業(yè)的熱點(diǎn),也是Spring框

    2024年02月01日
    瀏覽(16)
  • AOP(面向切面編程)

    AOP(面向切面編程)

    AOP?為?Aspect Oriented Programming?的縮寫,意為:面向切面編程,通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。AOP?是?OOP(面向?qū)ο缶幊蹋┑难永m(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn),也是?Spring?框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用?

    2024年02月05日
    瀏覽(21)
  • AOP 面向切面編程 入門練習(xí)

    添加依賴 Spring配置文件 接口類和實(shí)現(xiàn)類 切面類 測試類

    2024年04月11日
    瀏覽(19)
  • JAVA:面向切面編程AOP

    ? ? ? ? 把某一些功能提取出來與某一對(duì)象進(jìn)行隔離,提取之后可以對(duì)某哥單方面的功能進(jìn)行修改和擴(kuò)展 ? ? ? ? 也就是把眾多方法中的的所有公共代碼抽取出來,放到某個(gè)地方集中管理 ????????對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行了隔離,從而降低業(yè)務(wù)邏輯各部分之間的耦合,

    2024年02月07日
    瀏覽(17)
  • Spring面向切面編程(AOP)

    Spring面向切面編程(AOP)

    AOP(Aspect Oriented Programming),即面向切面編程,利用一種稱為\\\"橫切\(zhòng)\\"的技術(shù),剖開封裝的對(duì)象內(nèi)部,并將那些影響了多個(gè)類的公共行為封裝到一個(gè)可重用模塊,并將其命名為\\\"Aspect\\\",即切面。所謂\\\"切面\\\",簡單說就是那些與業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝

    2024年02月07日
    瀏覽(30)
  • Spring AOP:面向切面編程

    在軟件開發(fā)中,我們經(jīng)常會(huì)遇到一些橫切關(guān)注點(diǎn)(cross-cutting concerns),如日志記錄、事務(wù)管理和安全性等。這些關(guān)注點(diǎn)不屬于特定的模塊或類,而是橫跨整個(gè)應(yīng)用程序。傳統(tǒng)的面向?qū)ο缶幊谭椒ㄍ鶗?huì)將這些關(guān)注點(diǎn)與核心業(yè)務(wù)邏輯混雜在一起,導(dǎo)致代碼的可讀性和可維護(hù)性下

    2024年02月09日
    瀏覽(21)
  • [SSM]Spring面向切面編程AOP

    [SSM]Spring面向切面編程AOP

    目錄 十五、面向切面編程AOP 15.1AOP介紹 15.2AOP的七大術(shù)語 15.3切點(diǎn)表達(dá)式 15.4使用Spring的AOP 15.4.1準(zhǔn)備工作 15.4.2基于AspectJ的AOP注解式開發(fā) 15.4.3基于XML配置方式的AOP(了解) 15.5AOP的實(shí)際案例:事務(wù)處理 15.6AOP的實(shí)際案例:安全日志 IoC使軟件組件松耦合。AOP讓你能夠捕捉系統(tǒng)中經(jīng)

    2024年02月15日
    瀏覽(28)
  • 認(rèn)識(shí) spring AOP (面向切面編程) - springboot

    認(rèn)識(shí) spring AOP (面向切面編程) - springboot

    本篇介紹什么是spring AOP, AOP的優(yōu)點(diǎn),使用場景,spring AOP的組成,簡單實(shí)現(xiàn)AOP 并 了解它的通知;如有錯(cuò)誤,請(qǐng)?jiān)谠u(píng)論區(qū)指正,讓我們一起交流,共同進(jìn)步! 本文開始 AOP: 面向切面編程,也就是面向某一類編程,對(duì)某一類事情進(jìn)行統(tǒng)一處理; spring AOP: 是實(shí)現(xiàn)了AOP這種思想的一

    2024年02月14日
    瀏覽(25)
  • Spring AOP(面向切面編程)和方法攔截

    Spring AOP(面向切面編程)和方法攔截 Spring是一款廣泛使用的Java開發(fā)框架,提供了豐富的功能和工具,用于簡化企業(yè)級(jí)應(yīng)用程序的開發(fā)。其中一個(gè)重要的特性是面向切面編程(AOP)和方法攔截。本文將介紹Spring AOP和方法攔截的概念、工作原理以及在實(shí)際開發(fā)中的應(yīng)用。 在軟

    2024年02月05日
    瀏覽(23)
  • 切面的魔力:解密Spring AOP 面向切面編程

    切面的魔力:解密Spring AOP 面向切面編程

    目錄 一、AOP簡介 1.1 什么是AOP ? 1.2?什么是面向切面編程 ? 1.3?AOP 的特點(diǎn) 二、?AOP的基本概念解讀 2.1 AOP的基本概念 2.2 AOP 概念趣事解讀 三、代碼情景演示 3.1?編寫目標(biāo)對(duì)象(超級(jí)英雄們正常的行動(dòng)) 3.2 編寫通知類 3.2.1?前置通知 3.2.2 后置通知 3.2.3 異常通知 3.2.4 環(huán)繞通知

    2024年02月11日
    瀏覽(89)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包