AOP的一些基本概念:
- Joinpoint:指aop的织入位置,比如以下对象的构造函数或者普通方法或者其他任何系统执行点;
- Pointcut:joinpoint的表达方式,用一些编程语言表达出具体织入位置,可以通过指定方法名等等指出织入位置,如:
pointcut query():call(public * get*(..));
上面public * get*(…)就是指定的织入位置。
- Advice:表示横切逻辑,它是横切关注点逻辑的载体,这里面可以是日志,安全登录等等切入的逻辑,相当于Class中Method
- Aspect:是对系统中横切关注点逻辑进行模块化封装的AOP概念实体,相当于Class,Aspect可以包含多个Pointcut和Advice定义,如下:
aspect AjAspect
{
//pointcut定义
pointcut query():call(public * get*(..));
pointcut update():execution(public void update*(..));
...
//advice定义
before():query()
{
//横切逻辑
...
}
after() returnint:update()
{
//横切逻辑
...
}
...
}
StringAOP实现机制
StringAOP是第二代AOP,采用动态代理机制和动态字节码生成技术实现,与第一代在编译阶段使用编译器直接将横切逻辑织入目标对象不同,第二代是在运行阶段对目标对象生成一个代理对象,然后将横切逻辑织入代理对象中,系统最后使用了代理对象而不是目标对象。
- 静态代理模式:通常有4种角色,初始接口,实现类,代理类,访问者
如下图:
实现类就是我们要织入的目标类,实现了基层接口,访问者要想访问我们的目标类只能通过访问代理类来访问,不可直接访问目标类,代理类实现如下:
public class ProxySubject implements RealSubject
{
private RealSubject subject; //注入目标类
public Object Action()
{
//要织入的横切逻辑
//Action方法体逻辑
...
//要织入的横切逻辑
...
}
...
}
- 动态代理模式:在静态代理的基础上为了提高效率,为了减少有相同横切逻辑但不同类型代理对象的创建,有了动态代理,对于织入相同横切逻辑的不同类型目标对象只需要一个代理对象即可,实现动态代理,需要java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口,如下:
public class RequestInvocationHandler implements InvocationHandler
{
private Object target; //目标类注入
public Object invoke(Object proxy /*代理类*/,Method method,object[] args)
{
if(method.getName().equals("Action")) //找到Action()方法织入横切逻辑
{
//横切逻辑
...
//Action()方法体本身逻辑
...
//横切逻辑
...
return method.invoke(target,args);
}
return null;
}
}
以上实现都是基本目标类有一个基层接口,如果目标类没有接口可以实现,就用动态字节码;
- 动态字节码:对目标对象进行继承扩展,为其生成相应子类,然后将横切逻辑放入子类中,然后让系统使用拓展后的子类,要使用动态字节码需实现net.sf.cglib.proxy.Callbak接口或者net.sf.cglib.proxy.MethodInterceptor接口,如下:
public class RequestCallback implements MethodInterceptor
{
public Object intercept(Object object,Method method,Object[] args,MethodProxy proxy) throws Throwable
{
if(method.getName().equals("Action"))
{
...
//横切逻辑和Action()方法体逻辑
...
return proxy.invokeSuper(object,args);
}
return null;
}
}