说明:本文主要是讲解Spring AOP的来源,以及如何使用,同时对代理模式做简单的讲解;本文不分析源码执行过程,只是通过问题的形式来说明Spring Aop的来龙去脉。
Spring Aop是什么东西?
传统的开发模式是从上到下,也就是OOP了,而AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
我们为什么需要Aop?
1.分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
2.减少代码的重复,各个模块的重用性加强。
3.降低 模块间的耦合度,提高代码的可操作性和可维护性。
如果我们不适用AOP,那么必然会导致项目中的日志与具体的业务逻辑都写在一起,而且是每一个接口里面都需要日志,那么日志的代码数量远远超过具体业务逻辑代码,这样不利于后期的维护已修改。同时违背了软件设计的思想。如果使用的AOP,我们把这种不是必然需要的同时也是服务具体业务的模块单独分装起来,在业务逻辑前或后直接调用,从而提高代码的可操作性和可维护性。
那么Spring Aop又是如何实现的?
它的实现是基于典型的典型的代理模式实现的,它的实现思路是:定义一个抽象角色,让代理角色和真实角色分别去实现它。然后让真实角色去实现具体的业务逻辑,让代理对象实现具体业务逻辑前或后的一些事情,同时需要和真实角色说该你出场了(也就是需要在代理对象中传入真实对象,便于调用),最后实例化真实对象与代理对象,最后通过代理对象实现业务需求。在代理
模式中有两种类型,分别是静态代理与动态代理。这两种的实现思路基本一致,只不过动态代理不需要去我们自己创建一个代理对对象,可以用过JDK 动态代理和 CGLIB 动态代理来完成。
对代理模式的看法是什么?
一般都使用的是动态代理模式,在这需要说明一下动态代理的基本思路:首先实现InvocationHandler接口,然后通过java API创建代理类,最后动态加载代理类,代理类实现接口,使用handler(Proxy.newProxyInstance)以及调用invoke方法
代理模式与Aop有什么联系?
常见的实用场景有哪些?
1.事物的管理
2.日志管理
3.登录校验(拦截器的使用)
实例化参考:
确定切面
@Aspect
@Component
@Slf4j
public class SellerAuthorizeAspect {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 方法的验证
*
* @Pointcut :切入点,具体的路径,细化到名字的前缀
*/
@Pointcut("execution(public * com.zs.sell.controller.Seller*.*(..))" +
"&& !execution(public * com.zs.sell.controller.SellerUserController.*(..))")
public void verify() {
}
/**
* 具体实现
* Before:操作的顺序,在...之前操作
*/
@Before("verify()")
public void doVerify() {
//1.获取请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//2.查询cookie(便于验证是否登录过)
Cookie cookie = CookieUtil.getCookie(request, TokenConstant.TOKEN);
if (cookie == null) {
log.warn("【登录验证】cookie中没有查到数据cookie");
throw new SellerAuthorizeException();
}
//查询redis
String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEB_PREFIX, cookie));
if (StringUtils.isEmpty(tokenValue)) {
log.warn("【登录验证】redis中没有查到数据cookie");
throw new SellerAuthorizeException();
}
}
}
@Aspect:就是用来声明一个切面。这用写法是Aspectl的一种语法。
@Component:类似于xml中的,<bean>,向spring容器中添加类。
@Pointcut:就是切入点,某个类或方法。
execution(public * com.zs.sell.controller.Seller*.*(..)):Seller*代表的是以Seller开头的controller,*(..):表示所有的方法。
@Before:在操作之前的具体实现。
最后只需要做异常的捕获处理就行。