详解Sprin Aop(入门)

一、Aop是什么?

Aop就是面向切面编程,是对某一类事情的集中处理,是一种思想。
eg:在教务系统中,你想查询自己的成绩或者课表等,前提是登录后才能查,此时查询成绩、查询课表等这些业务都实现前都需要调用这个验证用户登录的方法,非常麻烦,而Aop思想就是在某一处配置一下,将这些业务的登录验证集中处理,每个需要验证登录的地方就可以实验验证,不用一个一个写相同的代码。

二、Spring Aop和Aop是什么关系?

Aop是一种思想,Spring Aop是一个框架,是对Aop思想的实现。

三、Aop可以用在哪里?

eg:
1、同一日志的处理;
2、同一方法执行时间统计;
3、同一返回格式设置;
4.同一异常的处理
等等…

四、Aop的组成

1、切面(Aspect)
定义Aop的业务类型,是实现某个功能的集合,类似java中的类。
2.连接点(Join Point)
需要被增强的某个Aop功能的所有方法。
3、切点(Pointcut)
一组规则,用来匹配连接点和增强,给满足规则的连接点添加通知。
4、通知(Advice)
定义了在切点中程序具体要做什么工作,什么时候使用等。
通知的类型:
(1)@Before:目标方法调用前执行;
(2)@After:目标方法调用后执行;
(3)@AfterReturning:目标方法返回后调用;
(4)@AfterThrowing:目标方法抛出异常后调用;
(5)@Around:在 join point 前和 joint point 退出后都执行。

看了上面的描述,你可能会有点懵,接下来举个例子来帮助理解:
现在有一个购买商品的功能,这个供就类似切面,浏览商品可以不用登录,但加入购物车或者直接购买商品需要登录,此时这个规则就类似于切点,里面需要进行登录验证的地方就是连接点,验证登录的这个方法体里面告诉你具体怎么验证登录就类似于通知

五、Aop怎样实现?

1、添加Spring Aop框架支持。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、定义切面切点和通知

//定义切面
@Aspect
@Component
public class UserAspect {

    //定义切点(拦截ConllerAop中所有请求)
    @Pointcut("execution(* com.example.first_mybits.controller.ControllerAop.*(..))")
    public void pointcut(){}

    //定义前置通知
    @Before("pointcut()")
    public void doAfter(){
        System.out.println("执行前置方法!");
    }
    //定义后置通知
    @After("pointcut()")
    public void doBefore(){
        System.out.println("执行后置方法!");
    }
}

3.测试

@ResponseBody
@Controller
@RequestMapping("/aop")
@Slf4j
public class ControllerAop {
    @RequestMapping("/hello")
    public String sayHello(){
        log.info("执行hello!");
        return "hello!";
    }
}

4.结果
在这里插入图片描述

示例:使用Aop统计UserController每个方法的执行时间

@Mapper
public interface UserMapper {
    public UserInfo getUserById(Integer uid);
}
<select id="getUserById" resultType="com.example.first_mybits.model.UserInfo">
        select * from userinfo where uid=#{uid}  <!--uid为getUserById这个方法的参数-->
    </select>
@Service
public class UserService {
    @Resource
    private UserMapper userMapper;//可以注入接口

    public UserInfo getUserById(Integer uid){
        return userMapper.getUserById(uid);//接口中的方法已经在mapper.xml中实现了,可以正常使用
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;//注入
    @RequestMapping("/getuserbyid")
    public UserInfo getUserById(Integer uid){
        if(uid!=null && uid>0){
            //参数有效
            return userService.getUserById(uid);//注入,调用
        }else {
            return new UserInfo();//返回空的UserInfo
        }
    }
}
//定义切面
@Aspect
@Component
public class TimeAspect {

    //定义切点
    @Around("execution(* com.example.first_mybits.controller.UserController.*(..))")
    public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        Object proceed = joinPoint.proceed();

        long end = System.currentTimeMillis();
        long time = end - start;

        System.out.println(joinPoint.getSignature().toShortString() + "执行时间:" + time + "ms");

        return proceed;
    }
}

结果:
在这里插入图片描述

你可能感兴趣的:(开发语言,javaee,spring)