当前位置: 首页 > 工具软件 > Aspect C++ > 使用案例 >

C++11 Aspect自实现

汪文光
2023-12-01

想加个类似spring里面的AOP,避免插桩式的编码,也方便代码复用。

虽然有AspectC++这个现成的轮子,但是看下了下也是静态的,根据AspectC++对应的语法使用自己的编译器编译的时候替换成C++代码语法,不是我想要的,引入是个麻烦事。

那就只能自己造了,写了一点,写的不怎么满意,只能说先凑活用,做不到JAVA那么灵活,先记录下来吧,后面有精力看看怎么完善吧。

以下只对C++11,如果有C++17,可以用 if constexpr 去掉下面重复的模板函数匹配,一坨参数匹配,写着难受看着难受。

/*
 * @Author: shanRX
 * @Date: 2022-02-24 15:23:06
 * @LastEditTime: 2022-02-28 10:01:00
 * @LastEditors: shanRX
 * @Description: 切面编织
 * 咸鱼本咸
 */

#include <functional>
#include <list>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>

template <typename T, typename... Args>
class HasAfterFunc {
    template <typename C = T>
    static auto test(int) -> decltype(std::declval<C>().after(std::declval<Args>()...), std::true_type());
    template <typename C = T>
    static std::false_type test(...);

public:
    enum {
        value = std::is_same<decltype(test(0)),
            std::true_type>::value
    };
};

template <typename T, typename... Args>
class HasBeforeFunc {
    template <typename C = T>
    static auto test(int) -> decltype(std::declval<C>().before(std::declval<Args>()...), std::true_type());
    template <typename C = T>
    static std::false_type test(...);

public:
    enum {
        value = std::is_same<decltype(test(0)),
            std::true_type>::value
    };
};


template<typename... Args>
class AspectWeaver
{
  public:
    template <typename AspectType>
    typename std::enable_if<std::is_class<AspectType>::value && HasBeforeFunc<AspectType, Args...>::value && !HasAfterFunc<AspectType, Args...>::value>::type
    addAspect(std::shared_ptr<AspectType> aspect)
    {

        m_beforeList.push_back([aspect](Args &&...args) { aspect->before(std::forward<Args>(args)...); });
    }

    template <typename AspectType>
    typename std::enable_if<std::is_class<AspectType>::value && HasBeforeFunc<AspectType, Args...>::value &&
                            HasAfterFunc<AspectType, Args...>::value>::type
    addAspect(std::shared_ptr<AspectType> aspect)
    {
        m_beforeList.push_back([aspect](Args &&...args) { aspect->before(std::forward<Args>(args)...); });
        m_afterList.push_front([aspect](Args &&...args) { aspect->after(std::forward<Args>(args)...); });
    }

    template <typename AspectType>
    typename std::enable_if<std::is_class<AspectType>::value && HasAfterFunc<AspectType, Args...>::value && !HasBeforeFunc<AspectType, Args...>::value >::type
    addAspect(std::shared_ptr<AspectType> aspect)
    {
        m_afterList.push_front([aspect](Args &&...args) { aspect->after(std::forward<Args>(args)...); });
    }

    template <typename FuncType>
    auto invoke(FuncType &&func, Args... args) -> decltype(std::declval<FuncType>()(args...))
    {
        for (auto iter : m_beforeList)
        {
            iter(args...);
        }
        auto r = func(args...);
        for (auto iter : m_afterList)
        {
            iter(args...);
        }
        return r;
    }

    private:
    std::list<std::function<void(Args...)>> m_beforeList;
    std::list<std::function<void(Args...)>> m_afterList;
};

#include <iostream>
class MyClass {
public:
    int func(int i)
    {
        i = i*i;
        std::cout << i << std::endl;
        return 0;
    }

    int func1(int i)
    {
        i += 1;
        std::cout << "this func1 " << i << std::endl;
        return 0;
    }
};

class Aspect1 {
public:
    void before(int i)
    {
        std::cout << "Aspect1 before" << std::endl;
    }
};

class Aspect2 {
public:
    void after(int i)
    {
        std::cout << "Aspect2 after" << std::endl;
    }
};

class Aspect3 {
public:
    void before(int i)
    {
        std::cout << "Aspect3 begin" << std::endl;
    }

    void after(int i)
    {
        std::cout << "Aspect3 end" << std::endl;
    }
};

int main(){
    AspectWeaver<int> weaver;
    weaver.addAspect(std::make_shared<Aspect1>());
    weaver.addAspect(std::make_shared<Aspect2>());
    weaver.addAspect(std::make_shared<Aspect3>());

    MyClass a;
    weaver.invoke(std::bind(&MyClass::func, &a, std::placeholders::_1), 1);

    weaver.invoke([&a](int PH1) { return a.func1(std::forward<decltype(PH1)>(PH1)); }, 1);
}

输出

Aspect1 before
Aspect3 begin
1
Aspect3 end
Aspect2 after
Aspect1 before
Aspect3 begin
this func1 2
Aspect3 end
Aspect2 after

此外还有参考网上 另外一种更静态的实现

/*
 * @Author: shanRX
 * @Date: 2022-02-24 15:23:06
 * @LastEditTime: 2022-02-28 10:01:00
 * @LastEditors: shanRX
 * @Description: 切面编织
 * 咸鱼本咸
 */

#include <functional>
#include <list>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>

template <typename T, typename... Args>
class HasAfterFunc {
    template <typename C = T>
    static auto test(int) -> decltype(std::declval<C>().after(std::declval<Args>()...), std::true_type());
    template <typename C = T>
    static std::false_type test(...);

public:
    enum {
        value = std::is_same<decltype(test(0)),
            std::true_type>::value
    };
};

template <typename T, typename... Args>
class HasBeforeFunc {
    template <typename C = T>
    static auto test(int) -> decltype(std::declval<C>().before(std::declval<Args>()...), std::true_type());
    template <typename C = T>
    static std::false_type test(...);

public:
    enum {
        value = std::is_same<decltype(test(0)),
            std::true_type>::value
    };
};

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

    template <typename T>
    typename std::enable_if<HasBeforeFunc<T, Args...>::value && HasAfterFunc<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<HasBeforeFunc<T, Args...>::value && !HasAfterFunc<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<!HasBeforeFunc<T, Args...>::value && HasAfterFunc<T, Args...>::value>::type Invoke(Args&&... args, T&& aspect)
    {
        m_func(std::forward<Args>(args)...); //核心逻辑
        aspect.after(std::forward<Args>(args)...); //核心逻辑之后的切面逻辑
    }

    template <typename Head, typename... Tail>
    typename std::enable_if<HasBeforeFunc<Head, Args...>::value && HasAfterFunc<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<!HasBeforeFunc<Head, Args...>::value && HasAfterFunc<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)...);
    }

    template <typename Head, typename... Tail>
    typename std::enable_if<HasBeforeFunc<Head, Args...>::value && !HasAfterFunc<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)...);
    }

private:
    Func m_func; //被织入的函数
};

template <typename T>
using identity_t = T;

// 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)..., identity_t<AP>()...);
}

#include <iostream>

class MyClass {
public:
    int func(int i)
    {
        i = i * i;
        std::cout << i << std::endl;
        return 0;
    }

    int func1(int i)
    {
        i += 1;
        std::cout << "this func1 " << i << std::endl;
        return 0;
    }
};

class Aspect1 {
public:
    void before(int i)
    {
        std::cout << "Aspect1 before" << std::endl;
    }
};

class Aspect2 {
public:
    void after(int i)
    {
        std::cout << "Aspect2 after" << std::endl;
    }
};

class Aspect3 {
public:
    void before(int i)
    {
        std::cout << "Aspect3 begin" << std::endl;
    }

    void after(int i)
    {
        std::cout << "Aspect3 end" << std::endl;
    }
};

int main()
{
    MyClass a;

    Invoke<Aspect1,Aspect2,Aspect3>(std::bind(&MyClass::func, &a, std::placeholders::_1), 1);
    Invoke<Aspect1,Aspect2,Aspect3>([&a](int PH1) { return a.func1(std::forward<decltype(PH1)>(PH1)); }, 1);
}

输出一致

Aspect1 before
Aspect3 begin
1
Aspect3 end
Aspect2 after
Aspect1 before
Aspect3 begin
this func1 2
Aspect3 end
Aspect2 after
 类似资料: