一. 点睛
AOP
:面向切面编程,是相对于OOP
面向对象编程而言的。
Spring的AOP
的存在目的是为了解耦。AOP
可以让一组类共享相同的行为。在OOP
中只能通过继承类和实现接口来实现,但是这样的缺点是会使代码的耦合度增加,且类继承只能为单继承,阻碍更多行为添加到一组类上,AOP
的出现弥补了OOP
的不足。
Spring支持AspectJ的注解式切面编程:
(1) 使用
@Aspect
注解在类上声明该类是一个切面。
(2) 使用@After
,@Before
,@Around
定义建言(advice
),可直接将拦截规则(切点)作为参数。
(3) 其中@After
,@Before
,@Around
参数的拦截规则为切点(PointCut
),为了使切点复用,可使用@PointCut
专门定义拦截规则,然后在@After
,@Before
,@Around
的参数中调用。
(4) 其中符合条件的每一个被拦截处为连接点(JoinPoint
)。
下面将通过模拟记录操作的日志系统的实现来演示基于注解拦截和基于方法规则拦截两种方式。其中注解式拦截能够很好的控制要拦截的粒度和获得更加丰富的信息,Spring
本身在事务处理(@Transaction
)和数据缓存(@Cacheable
等)上面都使用此种形式的拦截。
二. 示例
1. 添加spring aop支持以及AspectJ依赖。
<!-- spring aop支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- aspectj支持 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
2. 编写拦截规则的注解
package org.light4j.sping4.base.aop;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
代码解释:
这里说下注解,注解本身是没有任何功能的,就和xml是一样的。注解和
xml
都是一种元数据,元数据即解释数据的数据,这就是所谓的配置。
(3). 编写使用注解的被拦截类
package org.light4j.sping4.base.aop;
import org.springframework.stereotype.Service;
@Service
public class DemoAnnotationService {
@Action(name="注解式拦截的add操作")
public void add(){}
}
(4). 编写使用方法拦截规则的被拦截类
package org.light4j.sping4.base.aop;
import org.springframework.stereotype.Service;
@Service
public class DemoMethodService {
public void add(){}
}
(5). 编写切面
package org.light4j.sping4.base.aop;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Aspect //①
@Component //②
public class LogAspect {
@Pointcut("@annotation(org.light4j.sping4.base.aop.Action)") //③
public void annotationPointCut(){};
@After("annotationPointCut()") //④
public void after(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
System.out.println("注解式拦截 " + action.name()); //⑤
}
@Before("execution(* org.light4j.sping4.base.aop.DemoMethodService.*(..))") //⑥
public void before(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截,"+method.getName());
}
}
代码解释:
①通过
@Aspect
注解声明该类是一个切面。
②通过@Component
让此切面成为Spring
容器管理的Bean
。
③通过@Pointcut
注解声明切面。
④通过@After
注解声明一个建言,并使用@Pointcut
定义的切点。
⑤通过反射可以获得注解上面的属性,然后做日志记录相关的操作,下面的相同。
⑥通过@Before
注解声明一个建言,此建言直接使用拦截规则作为参数。
(6). 配置类
package org.light4j.sping4.base.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("org.light4j.sping4.base.aop")
@EnableAspectJAutoProxy //①
public class AopConfig {
}
代码解释:
①使用
@EnableAspectJAutoProxy
注解开启Spring
对AspectJ
的支持。
(7). 运行
package org.light4j.sping4.base.aop;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class); //1
DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);
demoAnnotationService.add();
demoMethodService.add();
context.close();
}
}
运行结果如下图所示:
(8). 源代码示例:
公众号ID:longjiazuoA

未经允许不得转载:人生设计师 » Spring4.x基础配置(三):Spring AOP