1.切入点表达式
1.1bean表达式
说明:根据dean的ID拦截指定的对象
@Pointcut("bean(userServiceImpl)")
public void pointcut(){
}
1.2within表达式
说明:按照类型匹配,可以使用通配符*号
语法:
1. @Pointcut("within(com.jt.service. UserServicelmpl) ")
//只拦截UserServicelml的类
2. @Pointcut( "within(com.jt.service. *)")
//拦截com.it.service下的一级的类.
3. @Pointcut( "within(com.jt.service.. *)")
//拦截 com.jt.service下的所有类
4. @Pointcut ( "within(com. * . service..*)")
//拦截com.任意包.service下所有包下的所有类
说明:上述的2种操作方法 粒度较粗,一般情况下不用
1.3execution表达式
作用:粒度比较细,可以按照方法参数进行匹配
语法:
语法: @Pointcut("execution(返回值类型 包名.类名.方法名(参数列表))")
1. 按照类型方法匹配
@Pointcut("execution(* com.jt.service.UserServiceImpl.addUser())")
2. 要求返回值任意, com.jt.service包下的所有的子孙类中的任意方法的任意参数要求拦截.
@Pointcut("execution(* com.jt.service..*.*(..))")
3. 要求返回值任意, com.jt.service包下的所有的子孙类中的add开头的方法并且参数1个是int类型 进行拦截
@Pointcut("execution(* com.jt.service..*.add*(int))")
1.4@annotation表达式
作用:可以根据用户的自定义注解拦截
1.4.1完成自定义注解Lyj
package com.jt.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //注解运行期有效
@Target(ElementType.METHOD) //注解标识 方法
public @interface Lyj {
}
1.4.2标记注解
1.4.3AOP拦截注解
2.关于通知的讲解
2.1关于AOP通知的用法
第一类:
1.@Before("pointcut()")
2.@AfterReturning( "pointcut()")
3.@AfterThrowing("pointcut()")
4.@After("pointcut()")
可以记录程序的执行的各个过程 为日志提供记录
第二类:
5.@around环绕通知 可以控制目标方法是否执行。环绕通知可以控制业务流转的过程!!!
例子:
1.权限的校验
2.缓存系统
3.异常的处理等
2.1.1通知中常用的API
需求:\
- 获取当前的目标对象的类型.\
- 获取当前的方法名称\
- 获取当前传递的参数.
常见报错: ProceedingJoinPoint is only supported for around advice ProceedingJoinPoint 只能用到环绕通知中.
//1.前置通知: 在目标方法执行之前执行.
@Before("pointcut()")
public void before(JoinPoint joinPoint){//连接点:获取方法中的数据
Class targetClass = joinPoint.getTarget().getClass();
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getSignature().getDeclaringTypeName();
Object[] objs = joinPoint.getArgs();
System.out.println("我是前置通知!!!!");
System.out.println("类型:"+ targetClass);
System.out.println("方法名称:"+methodName);
System.out.println("类的名称:"+className);
System.out.println("方法中携带的参数:"+ Arrays.toString(objs));
}
2.1.2后置通知用法
需求: 记录一下用户目标方法的返回值
说明: 通过属性returning 获取方法的返回值
//2.后置通知: 在目标方法执行之后执行
// 通过returning = "result"属性,获取目标方法的返回值,当作参数传递给result
@AfterReturning(value = "pointcut()",returning = "result")
public void afterReturn(Object result){
System.out.println("我是后置通知!!!!");
System.out.println("用户的返回值为:"+result);
}
2.1.3异常通知用法
说明: 如果用户执行业务方法时,报错了,则可以使用异常通知记录日志.
用法:
//3.异常通知: 目标方法执行报错时,执行该通知
@AfterThrowing(value = "pointcut()",throwing = "exception")
public void afterThrowing(Exception exception){
System.out.println("我是异常通知!!!!");
System.out.println("获取异常信息:"+exception.getMessage());
exception.printStackTrace();
}
2.2切面排序
说明:根据@Order注解 实现切面的排序
2.2.1编辑SpringAOP
//5.重点掌握 环绕通知: 在目标方法执行前后都要执行. 控制目标方法
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知A执行前!!!!");
//底层调用动态代理的invoke方法,执行目标方法
Object result = joinPoint.proceed();
System.out.println("环绕通知A执行后!!!!");
return result;
}
2.2.2编辑SpringAOP2
package com.jt.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component //将类交给spring容器管理
@Aspect //标识切面类
@Order(1) //AOP第一个执行 数字越小越靠前
public class SpringAOP2 {
//通过环绕通知 指定切入点表达式.
@Around("@annotation(com.jt.anno.Lyj)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//1.如果有下一个通知,则执行通知方法,没有通知,则执行目标方法
System.out.println("执行环绕通知B开始");
Object result = joinPoint.proceed();
System.out.println("执行环绕通知B结束");
return result;
}
}
2.3关于对象生成策略说明
默认策略:
1.Spring中默认的采用的动态代理的规则是JDK代理,如果被代理者没有接口,则自动使用CGLIB
2.如果需要修改为cglib代理,则添加如下代码
@Configuration
@ComponentScan("com.jt") //包扫描
@EnableAspectJAutoProxy(proxyTargetClass = true) //开启AOP
public class SpringConfig {
}
SpringBoot中默认代理模式采用CGLIB代理,如果需要修改为JDK代理则需要修改配置文件即可
3.关于Spring总结
1.为什么学习spring框架 让程序设计实现松耦合.
2.什么是面向接口编程 以后对象中的属性一般写接口. java中多态的体现. 属性类型更加的灵活 松耦合.
3.什么是IOC Ioc全称Inversion of Control,即“控制反转”,这是一种设计思想。对象创建的权利由 Spring框架完成.由容器管理对象的生命周期.
4.Spring容器启动方式 1. xml方式 2.注解方式
5.什么时候使用工厂模式: 1.对象不能直接实例化的时候. 2.spring框架整合其它第三方框架时使用. FactoryBean
6.单例多例问题: 默认条件下是单例模式 @Scope(“prototype”)
7.懒加载规则: 1. 默认条件下 懒加载无效 添加注解@Lazy 有效. 只对单例模式有效.
8.spring生命周期管理 4个过程: 1.对象创建 2. 对象初始化 @PostConstruct 3. 业务调用 4.对象销 毁 @PreDestroy
9.Spring中依赖注入的注解@Autowired 1.默认按照类型注入 2.可以按照名称注入 @Qualifier(“cat”) @Resource java中的注解.
10.MVC 设计思想 View 视图层 Model业务层 Control 控制层
10.根据MVC设计思想: 层级代码结构 Controller/Service/Mapper|Dao
11.@Value spring为属性动态赋值 基本类型和String和集合(几乎不用)
12.动态代理 JDK动态代理/CGLib动态代理
13.AOP 面向切面编程 在不改变源码的条件下对方法进行扩展.
14.AOP常见注解
1. @Aspect 标识切面
2. @Pointcut 标识切入点表达式 4种写法 2种常用
3. 五个通知注解
4. @EnableAspectJAutoProxy(proxyTargetClass = true) //开启AOP
5. 排序注解 @Order