C++11面向切面编程(AOP)入门指南

何为AOP

面向切面编程(AOP,Aspect Oriented Programming)是一种编程范式,允许开发者在不修改原有代码的情况下,为程序添加额外的功能。

什么是面向切面编程?

AOP的核心概念是切面(Aspect),它表示在程序中跨越多个功能模块的关注点。例如,日志记录、事务管理和权限控制等功能都可以视为切面。通过将这些关注点从业务逻辑中分离出来,实现对程序行为的模块化,从而提高代码的可读性和可维护性。
关键词:关注点分离,核心逻辑和非核心逻辑分离,核心关注点和切面关注点

核心概念

切面就是分布在各个业务模块里的非核心模块,大部分业务流程里都存在,因此aop就是为了把这些非核心逻辑关注点分离出来,比如日志模块。

在我们执行核心业务逻辑前后可以执行切面逻辑。

整个框架核心概念包括切面,切入点,通知,具体位置见下节。

  • 切入点就是目标函数,核心逻辑
  • 通知包括前置通知,后置通知,环绕通知(同时存在前置通知和后置通知)

图形化展示切面

在这里插入图片描述

AOP框架代码实现-C++11

参考《深入应用C++11代码优化与工程级别应用》

#include<type_traits>
#include<iostream>

#define HAS_MEMBER(member)\
template <typename T, typename... Args>\
struct has_member_##member\
{\
private:\
    template <typename U>\
    static auto Check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type());\
    template <typename U>\
    static std::false_type Check(...);\
public:\
    enum {value = std::is_same<decltype(Check<T>(0)), std::true_type>::value};\
};\

HAS_MEMBER(Before)
HAS_MEMBER(After)

#if 1
template <typename Func, typename... Args>
struct Aspect
{
    Aspect(Func&& f) : m_func(std::forward<Func>(f))
    {

    }

    template <typename T>
    typename std::enable_if<has_member_Before<T, Args...>::value && has_member_After<T, Args...>::value>::type
    Invoke(Args&&... args, T&& aspect)
    {
        aspect.Before(std::forward<Args>(args)...);
        m_func(std::forward<Args>(args)...);
        aspect.After(std::forward<Args>(args)...);
    }

    template <typename T>
    typename std::enable_if<has_member_Before<T, Args...>::value && !has_member_After<T, Args...>::value>::type
    Invoke(Args&&... args, T&& aspect)
    {
        aspect.Before(std::forward<Args>(args)...);
        m_func(std::forward<Args>(args)...);
    }

    template <typename T>
    typename std::enable_if<!has_member_Before<T, Args...>::value && has_member_After<T, Args...>::value>::type
    Invoke(Args&&... args, T&& aspect)
    {
        m_func(std::forward<Args>(args)...);
        aspect.After(std::forward<Args>(args)...);
    }
    
#if 1 // 改进的,SFINAE语法
    template <typename Head, typename... Tail>
    typename std::enable_if<has_member_Before<Head, Args...>::value && has_member_After<Head, Args...>::value>::type
    Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        headAspect.Before(std::forward<Args>(args)...);
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
        headAspect.After(std::forward<Args>(args)...);
    }

    template <typename Head, typename... Tail>
    typename std::enable_if<has_member_Before<Head, Args...>::value && !has_member_After<Head, Args...>::value>::type
    Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        headAspect.Before(std::forward<Args>(args)...);
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
    }

    template <typename Head, typename... Tail>
    typename std::enable_if<!has_member_Before<Head, Args...>::value && has_member_After<Head, Args...>::value>::type
    Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
        headAspect.After(std::forward<Args>(args)...);
    }

#else // 书上的
    template <typename Head, typename... Tail>
    void Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        headAspect.Before(std::forward<Args>(args)...);
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
        headAspect.After(std::forward<Args>(args)...);
    }
#endif

private:
    Func m_func;
};

// AOP 辅助函数
template<typename... AP, typename... Args, typename Func>
void Invoke(Func&& f, Args&&... args)
{
    Aspect<Func, Args...> asp(std::forward<Func>(f));
    asp.Invoke(std::forward<Args>(args)..., AP()...);
}


// test code
struct AA
{
    void Before(int i)
    {
        std::cout << "Before from AA " << i << std::endl;
    }

    void After(int i)
    {
        std::cout << "After from AA " << i << std::endl;
    }
};

struct BB
{
    void Before(int i)
    {
        std::cout << "Before from BB " << i << std::endl;
    }

    void After(int i)
    {
        std::cout << "After from BB " << i << std::endl;
    }
};

void Myfunc(int a)
{
    std::cout << "real Myfunc function: " << a << std::endl;
}
#endif

int main(void)
{
    Invoke<AA, BB>(&Myfunc, 1);

    return 0;
}

ps:书上针对多个切面的case时必须同时具备Before和After函数,见代码:

#else // 书上的
    template <typename Head, typename... Tail>
    void Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        headAspect.Before(std::forward<Args>(args)...);
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
        headAspect.After(std::forward<Args>(args)...);
    }
#endif

如何改进?
针对只包含Before或After和同时包含Before和After的场景编写函数模版,使用SFINAE技巧,核心就是利用std::enable_if类模版实现静多态(enable_if是基于C++中的SFINEA(Substitution failure is not anerror,中文直译即是“匹配失败不是错误”)实现的,SFINEA的意思是在实例化过程中,比如有三个模板,但凡能匹配到一个正确的,另外两个模板在实例化过程中即使报错,编译器也认为没问题),见代码:

#if 1 // 改进的,SFINAE语法
    template <typename Head, typename... Tail>
    typename std::enable_if<has_member_Before<Head, Args...>::value && has_member_After<Head, Args...>::value>::type
    Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        headAspect.Before(std::forward<Args>(args)...);
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
        headAspect.After(std::forward<Args>(args)...);
    }

    template <typename Head, typename... Tail>
    typename std::enable_if<has_member_Before<Head, Args...>::value && !has_member_After<Head, Args...>::value>::type
    Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        headAspect.Before(std::forward<Args>(args)...);
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
    }

    template <typename Head, typename... Tail>
    typename std::enable_if<!has_member_Before<Head, Args...>::value && has_member_After<Head, Args...>::value>::type
    Invoke(Args&&... args, Head&& headAspect, Tail&&... tailAspect)
    {
        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...);
        headAspect.After(std::forward<Args>(args)...);
    }

猜你喜欢

转载自blog.csdn.net/weixin_36623563/article/details/129973571