SSM整合-AOP介绍,以及登陆认证的使用
IOC 和 AOP是Spring的两大核心概念。也是面试的一个高频点
我看很多描述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还有其他好处:
- 假如说我有10处Controller都要调用这个Service方法,难道我要在10处不同controller里面 写上 VerifyUserAop 对象。
- 如果我不想要这些验证呢,那我又要一个个去删除
- 如果我不只是UserAccountServiceImpl 里面的某个方法要用这个重复代码,那我需要 调用VerifyUserAop对象的地方是不是更多了。然后如果我后面又要去掉呢?
AOP的另外一个好处就体现出来:配置方便
将当与我想知道你再做什么,OOP就像是在你家里装摄像头,AOP就是外挂,上帝视角。
当我不想看的时候,OOP还得去拆摄像头,外挂玩家表示,我不看就是了
那AOP怎么实现这些额外好处的,这得去看动态代理了,这篇博客只介绍AOP的概念(因为我的理解也不深刻,怕误导人)。
AOP的使用:
- 首先要再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>
- applicationContext里面加入,开启AOP注解
aop:aspectj-autoproxy/ - 编写提取出来的重复逻辑类,也就是切面,用@Aspect声明
- 写封装重复逻辑的方法,也就是增强,
- 在增强上 用@Before(“切入点表达式”),@After等表示位置
- 然后其他的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(修改错别字)