
Spring AOP的实现
概念H2
Aspect 切面,指的是切分多个类的模块化的关注点,包括Pointcut或Advice
bash
@Aspectpublic class NotVeryUsefulAspect {}
Join point 程序的执行点, 可用于插入代码 (在Spring里面指的是方法的执行)
Advice 对特定的Join point执行的动作
bash
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")public void doAccessCheck() {// ...}Pointcut 匹配Join point的断言
bash
@Pointcut("execution(* transfer(..))")// the pointcut expressionprivate void anyOldTransfer() {}// the pointcut signatureIntroduction 定义额外的方法或字段
Target Object 被一个或多个切面通知的目标对象
AOP proxy 由AOP框架创建的代理对象
Weaving 连接切面和应用对象来实现切面的功能
AOP的实现关键在于AOP代理的创建。代理对象可以分为静态代理和动态代理。
- 静态代理的实现 通过织入来创建静态的代理对象,AspectJ的实现就是这种方式
- 动态代理的实现 通过JDK动态代理或者CGlib来创建动态的代理对象,Spring AOP的实现就是这种方式
Spring AOPH2
Spring AOP采用的是动态代理的实现。配置AOP方式可以采用AspectJ的注解或者基于Spring的Schema的XML配置。
基于AspectJ的AOP配置H3
bash
@Aspectpublic class ConcurrentOperationExecutor implements Ordered {private static final int DEFAULT_MAX_RETRIES = 2;private int maxRetries = DEFAULT_MAX_RETRIES;private int order = 1;public void setMaxRetries(int maxRetries) {this.maxRetries = maxRetries;}public int getOrder() {return this.order;}public void setOrder(int order) {this.order = order;}@Around("com.xyz.myapp.SystemArchitecture.businessService()")public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {int numAttempts = 0;PessimisticLockingFailureException lockFailureException;do {numAttempts++;try {return pjp.proceed();}catch(PessimisticLockingFailureException ex) {lockFailureException = ex;}} while(numAttempts <= this.maxRetries);throw lockFailureException;}}
bash
<aop:aspectj-autoproxy/><bean id="concurrentOperationExecutor" class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor"><property name="maxRetries" value="3"/><property name="order" value="100"/></bean>
基于Schema的AOP配置H3
bash
<aop:config><aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor"><aop:pointcut id="idempotentOperation"expression="execution(* com.xyz.myapp.service.*.*(..))"/><aop:aroundpointcut-ref="idempotentOperation"method="doConcurrentOperation"/></aop:aspect></aop:config><bean id="concurrentOperationExecutor"class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor"><property name="maxRetries" value="3"/><property name="order" value="100"/></bean>
Spring中使用AspectJH3
AspectJ的通过静态代理来实现AOP的织入的。根据织入时机的不同,又分为编译时织入和类加载时织入(LTW)。Spring对AspjectJ的LTW进行了一定的增强,使得LTW能够针对于单个ClassLoader而不是整个JVM。
下面是个例子
首先定义AOP
bash
package foo;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Pointcut;import org.springframework.util.StopWatch;import org.springframework.core.annotation.Order;@Aspectpublic class ProfilingAspect {@Around("methodsToBeProfiled()")public Object profile(ProceedingJoinPoint pjp) throws Throwable {StopWatch sw = new StopWatch(getClass().getSimpleName());try {sw.start(pjp.getSignature().getName());return pjp.proceed();} finally {sw.stop();System.out.println(sw.prettyPrint());}}@Pointcut("execution(public * foo..*.*(..))")public void methodsToBeProfiled(){}}
然后定义需要织入的对象
bash
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"><aspectj><weaver><!-- only weave classes in our application-specific packages --><include within="foo.*"/></weaver><aspects><!-- weave in just this aspect --><aspect name="foo.ProfilingAspect"/></aspects></aspectj>
最后启用Spring的LTW
bash
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- a service object; we will be profiling its methods --><bean id="entitlementCalculationService"class="foo.StubEntitlementCalculationService"/><!-- this switches on the load-time weaving --><context:load-time-weaver/></beans>
评论
新的评论
上一篇
Hibernate使用outer join fetch集合时返回重复的结果
问题 如果我们有一个订单关联三个订单项,当进行下面的查询时 返回的结果集会是三个一样的订单对象,分别包含了三个订单项。 原因 首先在SQL层面LEFT JOIN会以左表为驱动表去关联从表的中的所有记录。以上面的的订单为例,就会返回三条纪录。而Hibernate默认会保留所有的驱…
下一篇
用Spring data rest开发基于HATEOAS的API
概念 首先,HATEOAS (Hypermedia as the Engine of Application State) 是REST应用架构的一个约束。一个 hypermedia-driven 的站点通过响应中的超媒体链接动态地提供了导航到站点的REST接口的信息。 下面是一…
