SSM整合-AOP介绍,以及登陆认证的使用

SSM整合-AOP介绍,以及登陆认证的使用

IOC 和 AOP是Spring的两大核心概念。也是面试的一个高频点
我看很多描述AOP都把其和动态代理结合在一起。让人一脸蒙蔽的进去,再一脸蒙蔽的出来(AOP的是用动态代理实现,但不代表就不能用了。我用个电冰箱也不代表我得知道制冷原理啊)

这篇文章不讲动态代理,仅描述AOP本身,以及如何使用。这篇文章比较浅,如果你想要更深入的知识,下面的可以不用看了

AOP面向切面编程,其主要功能就是将重复代码提取出来,进行复用

其主要功能是:将重复代码提取出来,进行复用

提取重复代码,进行复用

网上找的图,日志切面,权限切面就是各个不同模块(组件)里面的重复代码,我们仅写一次,三个都可以用
AOP
那其实:如果我把这些重复代码封装到一个类里面,再在各个模块里面调用这个类的对象进行复用,是否可以?
答:完全可以, 但是除了【将重复代码提取出来,进行复用】,使用AOP还有一些其他好处,这种方式就是OOP了,就是我们一般说的面向对象编程

我们将AOP和 通过类(面向对象编程)来封装代码来实现分复用效果进行对比。来解释AOP的一些概念
我的业务逻辑:查询用户账户信息的时候判断用户身份, 这里【判断用户身份】是重复逻辑,
最下面的示例代码分别是

  • 切面类 VerifyUserAop 就是用来封装[判断用户身份]逻辑的类
  • service类UserAccountServiceImpl 实现查询用户账户
  • Controller类,调用UserAccountServiceImpl 的类,AOP里面管这叫目标对象 target

用Java描述一遍:Controller调用service之前,先用VerifyUserAop 的方法判断是有有权限调用。

  • Aspect(切面):Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。 就是我的那VerifyUserAop ,用来封装重复代码的类
  • Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。 这个东西我的例子里面没用到,也不知道怎么描述
  • Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。 就是VerifyUserAop 对象插入的地方
  • Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。 就是VerifyUserAop里面的verifyLoginByCookie方法
  • Target(目标对象):织入 Advice 的目标对象.。 就是我要做身份验证的地方UserAccountController类
  • Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程 我把VerifyUserAop.verifyLoginByCookie 放到controller的过程

这样是不是好理解多了

我这里使用AOP实现的,实现的逻辑是每次调用UserAccountServiceImpl.listUserAccount方法之前,先执行我的重复代码,也就是执行我切面里面的增强
通过OOP也能实现【重复代码复用】的操作

但是AOP还有其他好处:

  1. 假如说我有10处Controller都要调用这个Service方法,难道我要在10处不同controller里面 写上 VerifyUserAop 对象。
  2. 如果我不想要这些验证呢,那我又要一个个去删除
  3. 如果我不只是UserAccountServiceImpl 里面的某个方法要用这个重复代码,那我需要 调用VerifyUserAop对象的地方是不是更多了。然后如果我后面又要去掉呢?

AOP的另外一个好处就体现出来:配置方便
将当与我想知道你再做什么,OOP就像是在你家里装摄像头,AOP就是外挂,上帝视角。
当我不想看的时候,OOP还得去拆摄像头,外挂玩家表示,我不看就是了

那AOP怎么实现这些额外好处的,这得去看动态代理了,这篇博客只介绍AOP的概念(因为我的理解也不深刻,怕误导人)。

AOP的使用:

  1. 首先要再POM里面加入包的依赖
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.5</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>
  1. applicationContext里面加入,开启AOP注解
    aop:aspectj-autoproxy/
  2. 编写提取出来的重复逻辑类,也就是切面,用@Aspect声明
  3. 写封装重复逻辑的方法,也就是增强,
  4. 在增强上 用@Before(“切入点表达式”),@After等表示位置
  5. 然后其他的Spring都会替你完成(我们之所以这么好用,是因为大佬把逻辑都封装好了,我们只需要专注业务开发)

完结;

底部:
切面类,也就是封装重复代码的类

package com.code.aop;
// 这里有一大堆导入包,但是我觉得太占屏幕了,给去掉了
/**
 * 切面类,用来验证用户是否登录
 * @author dengtiantian
 * Component 是加入IOC容器
 * Aspect是 声明为切面类
 */
@Component
@Aspect
public class VerifyUserAop {

    @Pointcut("execution(* com.code.service.impl.UserAccountServiceImpl.listUserAccount())")
    public void pointCut(){}

    @Before("pointCut()")
    public void verifyLoginByCookie(){
        System.out.println("AOP前置通知");
        /** 因为代码太长了。而且这里还不能将代码收起来,太占屏幕了**/
        // 下面的代码逻辑是 通过cookie来对登陆的身份进行验证,如果验证不通过,重定向到首页
    }

}

service类

package com.code.service.impl;
// 一堆import 我给去掉了
/**
 * @author dengtiantian
 * Service注解 意思是将对象加入IOC容器,在service层使用
 */
@Service("userAccountService")
public class UserAccountServiceImpl implements IUserAccountService {

    /**
     * Resource 是指定依赖关系。如果没有指定值,更具类型来找
     * 指定了值,更具名字来找
     * 我指定了值,与 com.code.dao.IUserAccountDao里的Repository匹配
     */
    @Resource(name = "userAccountDao")
    private IUserAccountDao userAccountDao;

    @Override
    public List<UserAccount> listUserAccount() {
        System.out.println("这里是UserAccountServiceImpl");
        System.out.println("测试实现接口:listUserAccount()");
        return this.userAccountDao.listUserAccount();
    }
    // 下面本来有一大批service方法,但是我觉得无关,给去掉了
}

Controller类

package com.code.controller;
// 这里有一大批import
/**
 * @author dengtiantian
 */
@Controller("userAccountController")
public class UserAccountController {
    /**
     * Resource 注解表示依赖哪个,如果没写自动的更具类型匹配,那肯定匹配到了IUserAccountService
     * 但是我要的是UserAccountServiceImpl 所以弄name准确匹配
     * 对应的com.code.service.impl.UserAccountServiceImpl里的service
     *
     */
    @Resource(name = "userAccountService")
    private IUserAccountService userAccountService;
    
    @RequestMapping(value = "/useraccount/listuseraccount",produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public String listUserAccount(HttpServletRequest request, HttpServletResponse response) throws IOException {
    
    	// 假如如果用OOP方式,这里就是我例子里面的切点 重复逻辑插入的地方
    	
        List<UserAccount> list = userAccountService.listUserAccount();
        String strJson = JSON.toJSONString(list);
        return strJson; 
    }
}

源码地址:https://gitee.com/dengtiantian/javaee_study.git

已收录

总目录:Java进阶之路-目录

                欲穷千里目,更上一层楼
                《登黄鹤楼》李白
                博主:五更依旧朝花落
                首次发布时间:2020年5月18日22:05:07
                末次更新时间:2020年5月19日10:55:50(修改错别字)

猜你喜欢

转载自blog.csdn.net/m0_37628958/article/details/106201011
今日推荐