AOP简介:

  面向切面编程

首先介绍动态代理:

动态代理可以在类的所有方法之前增加业务逻辑。jdk中的类想要被动态代理,必须实现接口(假设Target实现了接口ITarget)。使用proxy与实现InvocationHandler接口,来实现动态代理(参视频:动态代理)。PHandler实现InvocationHandler接口,其中含有private的Object(被代理对象target)。在自己的invoke方法(参见反射)中先写入自己的代理前业务逻辑,再通过反射方法调用被代理对象的对应方法(即method.invoke(target,args)),最后加上代理后业务逻辑。如果针对不同的业务逻辑增加不同的业务,可以将method传入PHandler的beforeMethod()方法,进而判断不同的method写入不同的beforeMethod方法内容。

实现动态代理的过程为:先产生一个被代理对象target,产生一个PHandler,将target用setter传给PHandler。然后使用ITarget targetProxy = Proxy.newProxyInstance(),将target与handler传入,传入方法为arg0:target.getClass().getClassLoader(),arg1:target.getClass().getInterfaces(),arg2:PHandler。handler中含有我们想加入的业务逻辑,target为被代理对象,含有原来的业务逻辑。

最后执行targetProxy.业务逻辑(业务参数);执行时先执行handler的begin逻辑,再执行target,最后执行handler的end逻辑。

Spring中的AOP实现,背后使用的是动态代理的实现(对有实现的类),对没有实现接口的类直接更改二进制码。

AOP的实现:

Java中实现AOP,需要在Spring的.xml中增加xmlns=“http://.../aop”,xsi:schemalocation中加schema/aop,schema/aop/spring-aop-2.5.xsd(可以在spring的samples中寻找例程,或者dist/resources寻找aop的.xsd)(在IDE的XML Catalog中增加后一个.xsd可以获得IDE的提示功能)。在.xml正文中增加<aop:aspectj-autoproxy/>,即可使用@AspectJ标签(程序会扫描@AspectJ标签并进行动态代理)。

AspectJ:AspectJ是一个专门用于产生动态代理功能的项目。Spring也使用了AspectJ进行AOP实现。使用AJ时要引入AspectJ的两个.jar包。

AOP的使用:

在类名前添加@Aspect标签(表示此类可以作为切面进行织入),并加入@Component(将此类交给Spring初始化,用于织入工作)。在想要在原逻辑前织入的业务逻辑(如beforeMethod())(其实也有将类,属性织入的,暂不讨论)上方加@Before标签(或任何Advice),即实现了将beforeMethod()织入原对象逻辑。

@Before的语法:

@Before("execution(public 返回值类型 com.company.dao.impl.UserDAOImpl.函数名(com.company.model.函数参数类名)”):将被@Before形容的方法织入到execution形容的函数名执行之前。execution是方法织入的专用关键词。

JoinPoint:

切入点,即在原逻辑中的哪些点需要织入切面逻辑;也即在从前往后的业务逻辑中插入切面时,在原逻辑中被织入的位置。

PointCut:

切入点的集合。

@Pointcut("execution(* com.company.someapp.service.*.*(..))")

public void someMethod(){}

代表在com.company.someapp.service下的任何类的任何方法都是someMethod()的切入点。

someMethod可以是空实现,作为Advice的参数。在此之后可以在任何Advice的参数中写someMethod(),即可在此切入点集合中执行。

Advice:

代表在切面上的建议逻辑。如@Before,@After都是切入点上的建议。

Target:

被代理对象(被织入对象)。

Weave:

织入。

 
AOP支持的AspectJ语法:

execution(public * *(..)):公开的任何返回值的任何方法

execution(* set*(..)):任何返回值的任何方法名为set打头的方法

execution(* com.comp.service.*.*(..)):任何返回值的service包下的任何类的任何方法

execution(* com.comp.service..*.*(..)):任何返回值的service包下及其子包(无限层)的任何类的任何方法

AOP自成语法:

within(com.comp.service.*):

within(com.comp.service..*):

this(com.comp.service.SomeService):

target(com.comp.service.SomeService):

args(java.io.Serializable):

etc.

 
Advice类型:

@before("execution()")或者Before(someMethod)[参见上PointCut解释]:

@AfterReturning:于目标方法正常返回后执行。

@AfterThrowing:于目标方法抛出异常后执行。

@After:即finally,不论异常或正常返回均执行。

@Around:环绕。被环绕修饰的方法public Object doBasicProfiling(方法名可换),参数为ProcedingJoinPoint pjp(不可换),throws Throwable。

在此方法中先写before织入逻辑,再写Object retVal = pjp.proceed();,再写after织入逻辑,最后 return retVal;。(可参责任链模式的视频)

Advice的参数可以是execution,也可以是someMethod[参见PointCut解释]

posted on 2016-05-31 23:22  hh6plus  阅读(251)  评论(0编辑  收藏  举报