AOP框架实现之一

       AOP实现的关键是动态织入,实现技术就是拦截目标方法,只要拦截了目标方法,我们就可以在目标方法执行前后做一些非核心逻辑,。

       通过继承方式来实现拦截的话,需要派生基类并且实现基类接口,这增加了程序的耦合性。为了降低耦合性,这里采用模板来约束。

       要求:每个切面必须有Before(Args...)或After(Args...)方法,用来处理核心逻辑执行前后的非核心逻辑。

 

      #define HAS_MEMBER(member) \

     template<typename T, typename...Args> struct has_member_ ##member\  #表示宏定义中的连接符,member是会发生变化的变量!

     { \

     private:\

               template<typename U> \

               static auto Check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type()); // 后面这句是什么意思啊?下面有is_same所以应该是

               返回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(Foo);

   HAS_MEMBER(Before);

   HAS_MEMBER(After);

   #include<NonCopyable.hpp>

   template<typename Func, typename...Args>

  struct Aspect : NonCopyable

  {

     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)...);

   }

   

    template<typename Head, typename...Tail>

    Invoke(Args&&...args, Head&& headAspect, Tail&& ...tailAspect)

    {

        headAspect.Before(std::forward<Args>(args)...);

        Invoke(std::forward<Args>(args)..., std::forward<Tail>(tailAspect)...); // 差点被骗了,这是一个循环执行函数!for执行多个类

        headAspect.After(std::forward<Args>(args)...);

   }

private:

  Func m_func;

};

template<typename T>

using identity_t =T;


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>()...); // 会执行多个Invoke中的类

}

上述代码中是为了让vs2013能识别出模板参数,采用

typename<typename T >

using identity_t = T;

因为各个编译期对参数的实现是由差异的,在GCC下(GCC????????),"Invoke(std::forward<Args>(args)..., AP()...)"是可以通过编译的,但是在

VS2013下就不能通过编译,通过identity_t能让VS2013正确识别出模板参数类型。

继承NonCopyable,使Aspect不可复制。

注:Before和After函数,和核心逻辑函数的入参保持一致,如果入参不一致,编译会报错;也可以通过这个约束在编译期就检查某个切面是否正确。

例:

struct AA

{

void Before(int i)

{

cout<<"Before from AA"<<i<<endl;

}

void After(int i)

{

cout<<"After from AA"<<i<<endl;

}

};

struct BB

{

 void Before(int i)

{

cout<<"Before from BB"<<i<<endl;

}

void After(int i)

{

cout<<"After from BB"<<i<<endl;

}

};

 struct CC

{

void Before()

{

cout <<"Before from CC"<<endl;

}

void After()

{

cout<<"After from CC"<<endl;

}

};

struct DD

{

void Before()

{

 cout<<"Before from DD"<<endl;

}

void After()

{

cout<<"After from DD"<<endl;

}

};

void GT()

{

 cout<<"real GT function"<<endl;

}

void HT(int a)

{
  cout<<"real HT function:"<<a<<endl;

}

void TestAop()

{

 // bind函数

std::function<void(int)> f = std::bind(&HT, std::placeholders::_1);

Invoke<AA, BB>(std::function<void(int)>(std::bind(&HT, std::placeholders_1)), 1);

Invoke<AA, BB>(f, 1);

// 函数指针

Invoke<CC, DD>(&GT);

Invoke<AA, BB>(&HT, 1);

// lambda表达式

Invoke<AA, BB>([](int i) {}, 1);

Invoke<CC, DD>([] {});

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值