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>(>);
Invoke<AA, BB>(&HT, 1);
// lambda表达式
Invoke<AA, BB>([](int i) {}, 1);
Invoke<CC, DD>([] {});