AOP的基本概念
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。
一 AOP的基本概念
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
JoinPoint的基本方法
AspectJ中的切入点匹配的执行点称作连接的(Join Point),在通知方法中可以声明一个JoinPoint类型的参数。通过JoinPoint可以访问连接点的细节。下面简要介绍JponPoint的方法:
1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
2.Signature getSignature() :获取连接点的方法签名对象;
3.java.lang.Object getTarget() :获取连接点所在的目标对象;
4.java.lang.Object getThis() :获取代理对象本身;
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
5.java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方 法;
6.java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的参数替换原来的参数。
代码
注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperateRecordAnnotation {
public String description() default "";
public String operateType() default "";
}
AOP方法
@Component
public class OperateRecordAspect {
private Logger logger= LoggerFactory.getLogger(OperateRecordAspect.class);
@Autowired
private OperateRecordService operateRecordService;
@Autowired
private UserService userService;
public void doAfter(JoinPoint joinpoint) {
HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String username=null;
String authorization = request.getHeader("Authorization");
OperateRecord operateRecord=new OperateRecord();
User userInfo = userService.getUserInfo(authorization);
if (userInfo !=null){
username=userInfo.getUsername();
}
String className = joinpoint.getTarget().getClass().getName();
String methodName = joinpoint.getSignature().getName();
Object[] args = joinpoint.getArgs();
if (args.length>0){
operateRecord.setOperParams(JSONObject.toJSONString(args));
}
try {
Class targetClass=Class.forName(className);
Method[] methods = targetClass.getMethods();
if (methods.length ==0) {
logger.info(className+" don't any methods");
return;
}
for (int i=0; i<methods.length;i++){
if (methods[i].getName().equals(methodName)){
Method method = methods[i];
OperateRecordAnnotation annotation = method.getAnnotation(OperateRecordAnnotation.class);
Parameter[] parameters = method.getParameters();
operateRecord.setDescription(annotation.description());
operateRecord.setOperType(annotation.operateType());
operateRecord.setOperMethod(className+"."+method.getName());
operateRecord.setOperator(username);
operateRecordService.addOperateRecord(operateRecord);
}
}
} catch (ClassNotFoundException e) {
logger.error("创建反射失败,失败原因是:"+e.getMessage());
} catch (Exception e) {
logger.error("添加日志失败,失败原因是:"+e.getMessage());
}
}
}
AOP配置信息
<!--配置日志-->
<!--其中的execution方法自己可以学-->
<aop:config>
<aop:pointcut id="operateRecord" expression="execution()"/>
<aop:pointcut id="checkconf" expression="execution(*)"/>
<aop:aspect ref="operateRecordAspect">
<aop:after method="doAfter" pointcut-ref="operateRecord"/>
<aop:after method="doAfter" pointcut-ref="checkconf"/>
</aop:aspect>
</aop:config>
方法
@OperateRecordAnnotation(description = "异常订单通过",operateType = "2")
@RequestMapping(value = "/unsafe/confirm",method = RequestMethod.POST)
public String unsafeConfirm(@RequestBody Order order) {
<!--业务-->
}