spring整合AspectJ

AOP的基本概念

@Aspect(切面): 通常是一个类,里面可以定义切入点和通知

JointPoint(连接点):  程序执行过程中明确的点,一般是方法的调用

Advice(通知):  AOP在特定的切入点上执行的增强处理:

               @Before:  标识一个前置增强方法,相当于BeforeAdvice的功能

               @After:  final增强,不管是抛出异常或者正常退出都会执行。

               @AfterReturning:  后置增强,似于AfterReturningAdvice, 方法正常退出时执行

               @AfterThrowing:  异常抛出增强,相当于ThrowsAdvice

               @Around: 环绕增强,相当于MethodInterceptor

Pointcut(切入点):   带有通知的连接点,在程序中主要体现为书写切入点表达式

AOP Proxy:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类。


遇到的问题

1.切点不好使

         原因,添加 @EnableAspectJAutoProxy 注解的时候添加错位置了,想要给controller添加通知,但是把该注解添加到了spring配置上面,spring容器中获取不到controller的bean,因此切点无法使用,正确应该是把该注解放到springmvc的配置上面.

参考链接:https://blog.csdn.net/wojiao228925661/article/details/82079957

2.通知了两遍

        原因,把切面类放在了spring容器和springmvc容器都可以扫描到的地方,生成了两个切面类,因此产生了两份通知.

参考链接:https://blog.csdn.net/zongzi_13595345262/article/details/84331328


开始使用

首先导入jar包

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aop</artifactId>
	<version>5.0.10.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
	<version>1.9.5</version>
</dependency>

添加注解(启动aspectj自动代理)

@EnableAspectJAutoProxy(proxyTargetClass =true)
proxyTargetClass 默认等于false 使用jdk动态代理
proxyTargetClass 等于true  使用cglib动态代理

注意事项:    在整合ssm框架的时候,spring和springmvc是分开扫描的,会产生两个容器,spring容器包含springmvc容器,controller之类的bean会被扫描到springmvc容器中,其他的普通bean在spring容器中,想对哪个容器中的bean进行拦截,就需要把该注解放在对应容器的代码上.不然无法拦截到对应的bean

创建切面类记录操作日志

package cn.yuexiang365.common.aop;

import java.time.LocalDateTime;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.yuexiang365.common.tools.RequestUtils;

/**
 * 系统日志,切面处理类
 *
 * @author shuai
 */
@Aspect
@Component
public class ApiLogAspect {
	
	private Log  log=LogFactory.getLog(getClass());
	

    /**
             * 设置切点
     */
    //@Pointcut("@annotation(cn.yuexiang365.common.annotation.ApiLog)") //通过注解的方式
    @Pointcut("execution(* cn.yuexiang365.controller.api..*Controller.*(..))")  //通过表达式的方式
    public void logPointCut() {

    }

    
    //环绕通知,此处只举一个通知例子,可以练习其他的通知
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        
        StringBuilder parameter=new StringBuilder();
        request.getParameterMap().forEach((key,value) ->  {parameter.append(key).append(":").append(ArrayUtils.toString(value));});
        log.info(new StringBuilder("request start---")
        		.append(RequestUtils.getIp(request)).append("  ")
        		.append(LocalDateTime.now()).append("  ")
        		.append(request.getRequestURI()).append("  ") 
        		.append(request.getMethod()).append("  ")
        		.append(parameter));
        Object result = point.proceed();
        return result;
    }


}

注意事项: 不要把该切面类既放在spring的容器扫描中,又放在springmvc的容器扫描中,不然就会产生两遍通知.

创建注解(如果切点处使用的是注解的方式)

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLog {

	
}

使用注解

    在需要进行拦截的方法上面添加自定义的注解即可

 

参考链接:

https://www.cnblogs.com/wm-dv/p/11735828.html

https://www.cnblogs.com/wwwzzz/p/7906128.html

https://blog.csdn.net/u010502101/article/details/78823056

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值