概念
AOP被称为面向切面编程,将一些共通处理进行封装得到一个切面。AOP可以理解为OOP的补充,没有AOP时,大量的日志记录代码散落在对象的各个层次,而这些代码与对象的核心功能并无关系。其他类型代码如鉴权、异常处理等都是如此。这样就导致大量代码重复,不利于模块的重用。实际中,springAop的应用和拦截器差不多,aop可以处理更为复杂的操作,比如前置通知、环绕通知等。
使用Aop需要先引入以下三个包一般使用org.aspectj提供的包,还有一个不带org的已经不维护了。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
</dependency>
<!-- 采用注解的方式配置bean需要加入这行,配置文件方式不需要 -->
<context:annotation-config />
<!-- 启用spring对AspectJ注解的支持 -->
<aop:aspectj-autoproxy />
aop中的各个概念
1、通过注解@Aspect声明一个切面,@PointCut声明切点表达式,切点表达式可以使用@annotation或execution来标识,@Before、@Around等声明通知类型。
Pointcut的定义包括两个部分
//定义切点表示式和Point签名,用来匹哪些方法执行通知(共通处理)
@Pointcut("execution(* com.changhf.aop.UserService.*(..))")
private void log(){}
使用pointcut时可以通过签名
@Before("log()")
//等同于 @Before("execution(* com.changhf.aop.UserService.*(..))")
@winthin()和@annotation的区别
@within()与 @annotation()括号里都是注解,两者区别前者的注解标在是对象级别,后者标在方法级别,用来匹配那些标记了注解的方法来执行通知
//任何类使用 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@within(org.springframework.transaction.annotation.Transactional)
//任何方法使用 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@annotation(org.springframework.transaction.annotation.Transactional)
within(com.changhf..*) //com.changhf包及子包下的任何方法执行
JoinPoint和ProceedingJoinPoint
JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:
ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法:
public interface ProceedingJoinPoint extends JoinPoint {}
常用通知注解包括@Before、@AfterReturning、@After、@AfterThrowing、@Around
拦截器
拦截器基于反射机制,通过继承springmvc提供的HandlerInterceptorAdapter
参考:java自定义注解(Annotation)和 java 反射
//在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制等处理;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
return true;
}
//在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView;
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {
}
//在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {
}