spring注解

  1. springConfig配置文件中的注解
  2. @Configuration //声明当前类为配置类
  3. @ComponentScan("com.itheima") //组件扫描
  4. @EnableAspectJAutoProxy //启动 AOP功能
  5. @Configuration //添加当前bean到ioc容器
  6. MyAdvice切面中的注解
  7. @Component //IOC配置: 当前bean需要加载到ioc容器中
  8. @Aspect //aop配置 : 声明当前类是切面类 (切面=切入点+通知)
  9. @Pointcut //指定切入点
  10. @Before 编写通知 @AfterReturning 后置通知
  11. @AfterThrowing 异常通知 @After 最终通知
  12. @Around // 环绕通知: 以上四种通知的结合
  13. 测试类中的注解
  14. @RunWith(SpringJUnit4ClassRunner.class) //spring整合junit
  15. @ContextConfiguration(classes = xx.class) //加载注解配置类
  16. IOC配置
  17. //IOC配置: 当前bean需要加载到ioc容器中
  18. @Controller //web层
  19. @Repository //dao层
  20. @Service //业务层
  21. @Component //其它(组件)
  22. springMVC中的配置
  23. @RequestMapping("/save") //设置映射路径为/save,即外部访问路径
  24. @ResponseBody //设置当前操作返回结果为字符串
  25. //ResponseBody注解加上类上,表示此类所有方法都有此注解
  26. @RequestParam //同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
  27. @RequestBody //在参数前面添加,用于接收json格式参数映射到pojo上
  28. @EnableWebMvc //开启json数据类型自动转换
  29. @DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss")
  30. //使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd
  31. @PathVariable //会将{id}中的值获取出来映射到对应的参数
  32. @RestController //@RestController = @Controller + @ResponseBody
  33. @RequestMapping("/user") // 提取共同父路径到类上
  34. @GetMapping @PostMapping @PutMapping @DeleteMapping
  35. //简化@RequestMapping的书写
  36. //举例 @RequestMapping(value = "/user",method = RequestMethod.GET)
  37. SpringBoot中的注解
  38. //SpringBoot注解 : 读取配置文件中前缀为enterprise
  39. @ConfigurationProperties(prefix = "enterprise")
  40. @SpringBootTest //设置JUnit加载的SpringBoot启动类
  41. @BeforeAll //测试方法执行之前运行一次,最早运行
  42. @BeforeEach //每个测试方法执行之前运行一次,二早运行
  43. @AfterEach //每个测试方法执行之后运行一次,三早运行
  44. @AfterAll //测试方法执行之后运行一次,四早运行
  45. //推荐 批量加载mapper接口 省略单个接口上的@Mapper
  46. @MapperScan("com.itheima.dao")
  47. 配置文件加载顺序
  48. # 按文件类型
  49. properties > yml > yaml
  50. # 按路径分类
  51. 当前project/config > 当前project > classpath/config > classpath
  52. # 按命令行设置
  53. jar包外的参数 > jar包内的参数

AOD面向切面编程

概述

  1. 切面 = 切入点 + 通知
  2. # 1. 介绍
  3. AOP(Aspect Oriented Programing)面向切面编程,一种编程范式,指导开发者如何组织程序结构
  4. OOP(Object Oriented Programing)面向对象编程
  5. # 2. 作用
  6. 在程序运行期间,不修改源码的基础上对已有方法进行增强
  7. (无侵入性: 耦合度低)
  8. # 3. 优势
  9. 1). 减少重复代码
  10. 2). 提高开发效率
  11. 3). 维护方便
  12. # 4. springAOP的实现方式
  13. 1). Bean实现接口时,Spring就会用JDK的动态代理
  14. 2). Bean没有实现接口时,Spring使用CGLib来实现
  15. JDK8之后, JDK动态代理效率高于CGlib
  16. 3). 备注: 开发者可以在spring中强制使用CGLib (了解)
  17. (在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)

大概步骤

  1. TODO:
  2. 1. 第一个执行的代码是main方法 -> 运行器中 SpringJUnit4ClassRunner
  3. 1). 解析ContextConfiguration注解 : 加载SpringConfig配置类
  4. 2. 加载SpringConfig配置类
  5. 1). @Configuration : 添加当前beanioc容器
  6. 2). @ComponentScan("com.itheima") : 组件扫描
  7. com.itheima包下的所有类,spring都知道,注解将可以被识别
  8. 3). @PropertySource("classpath:jdbc.properties")
  9. 加载外部配置文件
  10. 4). @Import(MybatisConfig.class)
  11. MybatisConfig放到ioc容器中
  12. 5). @Bean方法
  13. 创建DruidDataSource连接池对象,放到ioc容器中
  14. 3. @ComponentScan("com.itheima") : 组件扫描
  15. 1). @Service
  16. AccountServiceImpl类会被创建实例,放到ioc容器中
  17. 4. MybatisConfig里中有两个bean放到ioc容器

CGlib

  1. CGlib (Code Generation Library)
  2. 0. 也是一个动态代理技术
  3. 1. 不基于接口
  4. 代理类有无父接口都可以
  5. 2. 底层原理是继承
  6. 代理类直接继承被代理类,通过重写方法进行增强
  7. 3. 动态: 代理类不是静态定义的, 是在运行过程中动态生成的
  8. Spring AOP
  9. 0. 思想: 不惊动原始设计前提下, 增强功能
  10. 1. 被代理类有父接口, spring底层使用JDK Proxy
  11. 2. 被代理类没有接口, spring底层使用 CGlib
  12. JDK8开始, JDK Proxy的效率高于CGlib
  13. CGlib
  14. Code Generation library 代码生成库
  15. 1. 导包 : 第三方的库
  16. 2. 编写api

切入点表达式

  1. 1. 指定切入点
  2. /*
  3. 切入点表达式
  4. 1. 完整写法:execution(方法的修饰符 方法的返回值 类的全限定名.方法名(参数))
  5. public String com.itheima.service.impl.AccountServiceImpl.findAll()
  6. 2. 支持通配符的写法:
  7. 1) * 标识任意字符串
  8. 2) .. 任意重复次数
  9. 3. 规则
  10. 1. 方法的修饰符可以省略:
  11. String com.itheima.service.impl.AccountServiceImpl.findAll()
  12. 2. 返回值可以使用*号代替:标识任意返回值类型
  13. * com.itheima.service.impl.AccountServiceImpl.findAll()
  14. 3. 包名可以使用*号代替,代表任意包(一层包使用一个*)
  15. String com.itheima.*.*.AccountServiceImpl.findAll()
  16. 4. .使用.配置包名,标识此包以及此包下的所有子包
  17. String com.itheima..AccountServiceImpl.findAll()
  18. 5. 类名可以使用*号代替,标识任意类
  19. String com.itheima..*.findAll()
  20. 6. 方法名可以使用*号代替,表示任意方法
  21. String com.itheima..*.*(String)
  22. 7. 可以使用..配置参数,任意参数
  23. String com.itheima..*.*(..)
  24. 常用:
  25. * com.itheima.service..*(..)
  26. * com.itheima.service..xx(..)

编写通知

  1. . 编写通知
  2. 前置通知: 在切入点pt之前,执行xx方法
  3. @Before("pt()")
  4. public void xx(){
  5. System.out.println("111111111111111111");
  6. }
  7. //后置通知: 在切入点之后,执行
  8. @AfterReturning("pt()")
  9. public void afterReturning(){
  10. System.out.println("2222222222222");
  11. }
  12. //异常通知: 在切入点发生异常之后,执行
  13. @AfterThrowing("pt()")
  14. public void afterThrowing(){
  15. System.out.println("333333333333333333");
  16. }
  17. //最终通知: 在切入点执行完毕无论如何最终都会执行的
  18. @After("pt()")
  19. public void after(){
  20. System.out.println("44444444444444444");
  21. }
  22. 环绕通知: 以上四种通知的结合
  23. 1. 参数 : ProceedingJoinPoint
  24. 1). 切入点 : 表达式当前要被增强的方法
  25. 2). Object result = pjp.proceed();
  26. 切入点执行, 等价于 Object result = method.invoke(目标对象,args);

事务代理小案例

  1. CGlib (Code Generation Library)
  2. 0. 也是一个动态代理技术
  3. 1. 不基于接口
  4. 代理类有无父接口都可以
  5. 2. 底层原理是继承
  6. 代理类直接继承被代理类,通过重写方法进行增强
  7. 3. 动态: 代理类不是静态定义的, 是在运行过程中动态生成的
  8. Spring AOP
  9. 0. 思想: 不惊动原始设计前提下, 增强功能
  10. 1. 被代理类有父接口, spring底层使用JDK Proxy
  11. 2. 被代理类没有接口, spring底层使用 CGlib
  12. JDK8开始, JDK Proxy的效率高于CGlib
  13. CGlib
  14. Code Generation library 代码生成库
  15. 1. 导包 : 第三方的库
  16. 2. 编写api

代理模式

装饰模式(静态代理)

  1. 创建一个代理类对象
  2. 装饰模式(静态代理)
  3. I. 操作
  4. 1). 创建被代理类对象
  5. 2). 创建代理类对象
  6. 3). 代理类对象调用方法
  7. II. 公式
  8. 1). 角色
  9. a. 代理类
  10. b. 被代理类
  11. c. 共同的父类或父接口
  12. 2). 代理类实现被代理类的父接口
  13. 3). 代理类中接收被代理类对象(接口类型)
  14. 4). 代理类的方法在被代理类的方法基础上进行增强
  15. III. 对比继承
  16. 1). 继承只能增强父类UserServiceImpl
  17. 2). 而装饰模式的代理类可以增强UserService接口所有实现类
  18. BufferedReader br = new BufferedReader(new FileReader("a.txt"));
  19. br.read();
  20. ======================================================================
  21. 接口 UserService 中方法 void save();
  22. 接口实现类 UserServiceImpl 重写 方法 被代理类
  23. 测试类
  24. @Test
  25. public void test02() throws Exception {
  26. // 1). 创建被代理类对象
  27. UserServiceImpl userService = new UserServiceImpl();
  28. // 2). 创建代理类对象
  29. UserServiceProxy proxy = new UserServiceProxy(userService);
  30. // 3). 代理类对象调用方法
  31. proxy.save();
  32. 被代理类
  33. package com.itheima.service.impl;
  34. import com.itheima.service.UserService;
  35. public class UserServiceImpl implements UserService {
  36. @Override
  37. public void save() {
  38. // System.out.println("开启事务");
  39. System.out.println("UserServiceImpl save...");
  40. // System.out.println("成功提交,失败回滚");
  41. }
  42. @Override
  43. public void insert() {
  44. System.out.println("UserServiceImpl insert...");
  45. }
  46. }
  47. 代理类对象
  48. package com.itheima02;
  49. import com.itheima.service.UserService;
  50. // 代理类实现被代理类的父接口implements UserService
  51. public class UserServiceProxy implements UserService {
  52. // 代理类中接收被代理类对象(接口类型)
  53. private UserService userService;
  54. public UserServiceProxy(UserService userService){
  55. this.userService = userService;
  56. }
  57. @Override
  58. public void save() {
  59. // 代理类的方法在被代理类的方法基础上进行增强 事务
  60. System.out.println("开启事务");
  61. userService.save();
  62. System.out.println("成功提交,失败回滚");
  63. }
  64. @Override
  65. public void insert() {
  66. System.out.println("开启事务");
  67. userService.insert();
  68. System.out.println("成功提交,失败回滚");
  69. }
  70. }
  71. 打印结果
  72. 开启事务
  73. UserServiceImpl save...
  74. 成功提交,失败回滚

动态代理

  1. *底层实现一个类去实现接口
  2. I. 操作
  3. 1). 创建被代理类对象
  4. 2). 创建代理类对象
  5. 3). 代理类对象调用方法
  6. II. 公式
  7. 1). 角色
  8. a. 代理类
  9. b. 被代理类
  10. c. 共同的父类或父接口
  11. 2). 代理类实现被代理类的父接口
  12. 3). 代理类中接收被代理类对象(接口类型)
  13. 4). 代理类的方法在被代理类的方法基础上进行增强
  14. II. 动态
  15. 代理类无需静态定义(写出来),是在运行过程中动态生成 (反射)
  16. III. 对比装饰模式
  17. 优势: 代理类无需定义,提高开发效率
  18. 反射的作用: 抽取相同规律的代码
  19. =======================================================================测试类
  20. @Test
  21. public void test03(){
  22. // 1). 创建被代理类对象
  23. UserServiceImpl userService = new UserServiceImpl();
  24. // 2). 创建代理类对象
  25. /*
  26. * TODO:
  27. * Proxy.newProxyInstance(loader,interfaces,h);
  28. * 底层原理
  29. * 1. 实现类接口 : 底层会创建一个类实现接口,就会有字节码
  30. * 2. 类加载器 :
  31. * 1). 基本上都是第三方的类,一般是应用类加载器
  32. * 2). 上述的字节码需要类加载器进行加载,产生Class对象
  33. *
  34. * */
  35. Class<?>[] interfaces = userService.getClass().getInterfaces();
  36. // Class<?>[] interfaces = {UserService.class};
  37. ClassLoader loader = userService.getClass().getClassLoader();
  38. // ClassLoader loader = Demo.class.getClassLoader();
  39. InvocationHandler h = new InvocationHandler() {
  40. /*
  41. * 代理类对象调用任何方法,都将执行invoke方法
  42. * */
  43. @Override
  44. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  45. //执行被代理类对象的方法,等价于 userService.xx(args);
  46. System.out.println("开启事务");
  47. Object object = method.invoke(userService,args);
  48. System.out.println("成功提交,失败回滚");
  49. return object;
  50. }
  51. };
  52. UserService proxy = (UserService)Proxy.newProxyInstance(loader,interfaces,h);
  53. // 3). 代理类对象调用方法
  54. proxy.insert();
  55. }
  56. 被代理类
  57. public class UserServiceImpl implements UserService {
  58. @Override
  59. public void save() {
  60. // System.out.println("开启事务");
  61. System.out.println("UserServiceImpl save...");
  62. // System.out.println("成功提交,失败回滚");
  63. }
  64. @Override
  65. public void insert() {
  66. System.out.println("UserServiceImpl insert...");
  67. }
  68. }
  69. 代理对象 底层创建的 (伪代码 帮助理解)
  70. //模拟动态代理的代理类 !!!
  71. // 代理类实现被代理类的父接口implements UserService
  72. public class JdkProxy implements UserService {
  73. // 代理类中接收被代理类对象(接口类型)
  74. private InvocationHandler h;
  75. public JdkProxy(InvocationHandler h) {
  76. this.h = h;
  77. }
  78. /* @Override
  79. public void save(String name,int age) {
  80. Method save = this.getClass().getMethod("save");
  81. Object[] args = {name,age};
  82. Object object = h.invoke(this,save,args);
  83. return object;
  84. }*/
  85. @Override
  86. public void save() {
  87. try {
  88. Method save = this.getClass().getMethod("save");
  89. Object[] args = null;
  90. h.invoke(this,save,args);
  91. } catch (Throwable throwable) {
  92. throwable.printStackTrace();
  93. }
  94. }
  95. @Override
  96. public void insert() {
  97. // h.invoke();
  98. }