AOP:
什么是AOP:
AOP全称Aspect Oriented Programming,也称为面向切面编程。AOP是面对对象编程的有效补充,适用于具有横切逻辑的场合,比如日志记录、登录拦截、安全控制等。
为什么使用AOP:
使用AOP可以在不修改业务代码的情况下为业务代码增加新的功能,对代码段进行增强处理。可以把分散在代码中的重复代码提取出来进行统一的维护和控制。比如不使用AOP时,日志记录需要在每一个需要记录的方法中通过log4j记录,这样会有大量的重复代码,而使用AOP我们可以将方法所在的类作为切点,采用环绕通知,在方法执行前后完成日志记录。
AOP底层:
AOP底层通过代理实现,简单来说代理是由代理类去调用实现类的方法,在调用实现类方法前后可以在代理类中加入新的代码以实现新的功能。没有修改实现类的代码,却对实现类代码进行了增强。代理分为动态代理和静态代理,AOP采用动态代理,默认使用JDK动态代理实现,但是JDK动态代理需要接口的支持,在没有接口的情况下,也可以使用CGLIB动态代理实现。
AOP如何使用:
首先要引入AOP的依赖
<!-- aop动态代理需要的jar包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.2</version>
</dependency>
我觉得使用AOP有两点比较重要:切面类和切点。过程:我们可以创建一个普通类,在普通类上加上@Aspect注解标明这个类是一个切面类,加上@component注解标明这个类会交给Spring管理,在切面类中创建一个方法并加上通知的注解,如@Around,注解的value值是切点表达式,也就是实现方法的路径。切面类创建完成后通过需要在SpringMVC核心配置文件中加入<context:component-scan base-package="com.fh.handler" />标签,base-package后是切面类的路径,这个标签的作用是扫描包路径下的类,如果类上有component注解以及其子注解,则将类交给Spring管理。
<!-- 开启注解 -->
<mvc:annotation-driven/>
<!--为切面自动创建代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 扫描包路径 -->
<context:component-scan base-package="com.fh.handler" />
AOP环绕通知
package com.fh.handler;
import com.fh.annotation.MethodProcess;
import com.fh.entity.Log;
import com.fh.entity.User;
import com.fh.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;
@Component
@Aspect
public class PreHandler {
@Autowired
private LogService logService;
//切点表达式
@Around("execution(* com.fh.controller.*.*(..))")
public Object preHandler(ProceedingJoinPoint point){
Object proceed = null;
Log log = new Log();
try {
proceed = point.proceed();
log.setCreateDate(new Date());
log.setMethodName(point.getSignature().getName());
//获取到方法介绍
Signature signature = point.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod();
if(targetMethod.isAnnotationPresent(MethodProcess.class)){
log.setMethodPro(targetMethod.getAnnotation(MethodProcess.class).value());
}
//获取到用户
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession(true);
User user = (User) session.getAttribute("user");
log.setUserName(user.getUserName());
logService.addLog(log);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return proceed;
}
}