如何把注解和注解解析器联系起来?
如果不结合起来,就会把很多方法给切到,导致当前的注解逻辑用到很多方法上。
1)通过方法签名判断,当前方法上是否使用了这个注解。
2)直接把切面表达式设置成这个注解;只有使用了这个注解的方法,才会执行注解解析逻辑。
切点表达式的两种写法。使用注解的写法更好。
@Pointcut("@annotation(注解全类名)")
例如:
匹配标注了@RequestMapping的所有方法
@annotation(org.springframework.web.bind.annotation.RequestMapping)
切面类:主要用于描述约定的流程。
通过注解来定义各种通知类型。
1、切点(Pointcut):向Spring描述哪些类的哪些方法需要启动AOP编程。切点要配合正则表达式才能起作用。切点表达式,
2、使用@Pointcut注解来定义切点,它标注在pointCut方法上,则在后面的通知注解中就可以使用方法名称来定义。
3、aop增强:定义新的接口和实现类,不修改原有的服务接口和实现类;@DeclareParents,它的作用是引入新的类来增强服务,但它有两个必须配置的属性value和defalutImpl。两个实现类。
通知获取参数:通知如何获取参数?通过正则获取参数。
将连接点(目标对象方法)名称为user的参数传递进来。
自定义注解:输出方法的参数和返回值.
环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。
简单理解,环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的。
通过注解判断用户的登陆权限。
如何在项目中使用自定义注解?如何通过注解的方式实现当前功能?
SpringBoot自定义注解, 作用:简化操作。
流程:定义注解,使用注解,扫描注解,解析注解。 已经实现了功能。
使用注解进行逻辑判断:在注解逻辑中,如果出现问题,直接抛出异常;如果没有出现异常,在调用目标对象原有的方法。
1)使用自定义注解实现日志功能
2)使用自定义注解实现bean的实例化
package com.pica.cloud.base.api.workstation.server.anno;
import com.pica.cloud.foundation.entity.PicaException;
import com.pica.cloud.foundation.entity.PicaResultCode;
import com.pica.cloud.foundation.utils.controller.BaseController;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class VisitPermissionUtils extends BaseController {
private Logger logger = LoggerFactory.getLogger(VisitPermissionUtils.class);
/**
* 用户访问权限
*/
@Pointcut("execution(public * com.pica.cloud..*Controller.*(..))")
public void checkUserPermission() {
}
/**
* 判断用户的访问权限
*
* @param joinPoint
*/
@Before("checkUserPermission()")
public void beforeProcess(JoinPoint joinPoint) {
Integer currentHospitalId = super.fetchPicaUser().getHospital_id();
Long hospitalId = null;
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
hospitalId = (Long) args[0];
}
if (hospitalId != null && hospitalId.intValue() > 0) {
if (hospitalId.intValue() != currentHospitalId) {
logger.info("暂无访问权限");
throw new PicaException(PicaResultCode.PERMISSION_NO_ACCESS);
}
}
}
}
Spring IoC 的实现机制:
Spring 中的 IoC 的实现原理就是工厂模式加反射机制。
核心概念
连接点,切点,切面(类),织入(动态代理对象,约定流程),五种通知,原有目标对象方法以及参数。
要对哪些类的哪些方法进行增强.
通过注解标识通知类型。
切点表达式:通过切面表达式确定要扫描的范围,扫描当前表达式范围内,哪些类或方法使用了自定义的注解。
要想把一个类变成切面类,需要两步:
① 在类上使用 @Component 注解 把切面类加入到IOC容器中。② 在类上使用 @Aspect 注解 使之成为切面类。
前置通知:目标方法执行之前执行
@Before,参数类型JoinPoint
ProceedingJoinPoint,通知和切点相关联。
spring AOP原理:把当前方法织入某个流程中。
当然@Transacation这只是AOP的一种约定编程,被它注解的代码说明需要开启事务运行,Spring帮你把insertUser方法织入类似上图的流程中,数据库连接的打开和关闭以及事务管理都由它给你默认实现,也就是它可以将大量重复的流程通过约定的方式抽离出来,然后给与默认实现。例如这里的数据库打开释放,事务的处理和大量的try…catch…finally语句代码块。
这里没有任何数据库打开和关闭的代码,也没有事务回滚和提交的代码,却实现了数据库资源的打开和关闭以及事务的回滚和提交。(开启事务的回滚和提交)
数据库资源的打开和关闭是由谁做的?
连接点(join point )
切点:一系列连接点,需要通过正则表达式进行匹配。
通知(advice): 就是按照约定的流程下的方法,分为前置通知(before advice),后置通知(after advice),环绕通知(around advice),事后返回通知(afterReturning advice),异常通知(afterThrowing advice),它会根据约定织入流程中,需要弄明白它们在流程中的顺序和运行的条件。(约定流程下的方法)
织入(weaving):它是一个通过动态代理技术,为原有服务对象生成代理对象,然后将与切点定义匹配的连接点拦截,并按照约定将各类通知织入约定流程的过程。
通过反射机制实现动态代理。
首先要确定需要拦截什么方法,让它能织入约定的流程中。
首先需要确定连接点(什么类的什么方法)的问题。要对哪一个方法增强功能?
有了连接点,我们还需要一个切面,通过它可以描述AOP的信息和流程的织入。(切面类)
切面类中使用注解标识通知的类型。
六个注解,对应五种通知类型。
环绕通知:取代原有目标对象方法的通知,提供了回调原有目标对象方法的能力。原有目标对象
切点(Pointcut):向Spring描述哪些类的哪些方法需要启动AOP编程。代码中,使用了注解@Pointcut来定义切点。
通过添加接口来增强接口的功能,检验数据是否为空?
将原目标对象方法的参数传递到前置通知里面。
织入:是一个生成动态代理对象并且将切面和目标对象方法变成成为约定流程的过程。通过约定可以将一些业务逻辑织入流程中,并且可以将一些通用的逻辑抽离出来,然后给与默认实现。
Spring采用了JDK和CGLIB实现动态代理。
Spring可以支持多个切面的运行。
现在我们想对sayHello方法进行一个拦截,再方法的前后再增加一些方法,这些增加的方法和原方法sayHello组成一套约定的流程。
约定流程。
动态代理
我们先理解一下什么是动态代理。例如,当你需要采访一名儿童时,首先需要经过他父母的同意,在一些问题上父母会替他回答,而另外一些问题,父母觉得不太适合这个小孩会替孩子拒绝掉,显然父母就是这名儿童的代理(proxy)。通过代理可以增强或者控制对真实对象的访问。代理模式的作用