当前位置:   article > 正文

spring 6.0_spring6.0

spring6.0

spring6.0

1.认识spring 是一种轻量级的javaEE 框架。

spring  分为广义和狭义之分

 广义:指通过spring framework 为中心和spring技术栈。

狭义:spring framework 我们称之为spring。

1.2spring   核心技术   

spring core 包下 两大核心技术点

 ioc (inversion of contol) 控制反转,ioc是一种思想,是指我们创建资源变成我们索要资源。也就是说我们把bean 对象交给ioc容器进行管理,进行对象的创建,以及依赖关系的维护,可以帮助我们降低耦合,提高程序的可扩展性。

aop (aspect orienten programming) 的简写 称之为面向切面编程。是指用来封装多个类的公共行为,将于业务无关,却与业务模块所公共的调用封装起来,减少代码的重复性。降低耦合性,aop 还解决了系统的公共行为,如日志,事务,权限等。

1.3 spring framework 的特点

     减少侵入性:使用spring进行开发时,spring对代码结构影响小,对领域模型可以做到零污染。对功能开发也就是添加几个注解,不会破坏原有结构,这也就使得代码变得非常清洁,非常优雅。

     ioc

     aop

     容器:我们所说的 ioc 就是一种容器,帮助我们实现bean 的生命周期管理。替代了大量的创建细节,降低了使用门槛,大幅度提高了开发效率。

     组件化:spring实现了大量的组件配置成一个复杂的应用,再spring中可以通过xml 和注解组合这些对象,这使得我们可以有一个功能明确,边界清晰的组件有条不紊的的搭建各种复杂应用。

    一站式: 在ioc 和aop 的基础上我们可以整合各种优秀的开源框架和各种第三方库类。并且spring旗下也覆盖了广泛的领域,很多功能可以进行实现。

1.4 spring 组件

   ​编辑

1.5 spring 版本依赖

    jdk 17 

1.6 具体案例

  1.引入依赖

​编辑

   引入日志​编辑

 ​

引入log4j2.xml 日志配置文件都是固定的。

2.IOC

   ​

DI:依赖注入 依赖注入  用来实现控制反转的思想。

     分为两种方式:

     1.set方法注入。

      2. 构造方法注入。 

案例:

创建xml文件

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="org.example.bean.bo.User"/> </beans>

编写代码 :创建do,找到bean的xml 文件   通过上下文 获取bean​编辑

ioc 容器干了什么:

​编辑

Bean 管理说: 是只bean 对象的创建,bean属性中的赋值,以及维护对象间的关系。

 ioc 在spring中的实现:

   在创建bean 之前需要创建ioc容器,创建ioc 容器有两种方法:

  1. beanFactory

  ioc容器实现的基本实现,是spring 面向内部的接口,不提供给开发人员。

   2.ApplicationContext

  是beanFactory 的子接口,提供了更多高级特性,面向spring使用者,几乎所有场合都可以使用,而不是使用beanFactory。​编辑

bean的其他案例,暂不演示。

Bean 的作用域

​编辑

 Bean 的生命周期

1.bean的创建(调用无参构造)

2.bean 的属性赋值

3.bean的后置处理器 调用之前

4.对象初始化 (指定初始化方法)

5.bean 的后置处理器

6.bean 的使用

7.bean的销毁

8.ioc 容器关闭

​编辑

​编辑

FactoryBean

是bean 的一种,一般用来实现复杂的bean 的注入,spring帮我们把复杂的实现细节隐藏,对外暴露简单的bean,供我们使用。如mybaitis 的sqlSessionFactory  就是用FactoryBean 帮我们实现的。

​编辑

 实现FactoryBean 的接口

​编辑

获取bean 即可​编辑 

 2.自动注入

从Java5开始,Java增加了对追截的支持,他是代码中的一种特殊标记,可以在编译、类加载和运行时被读取,执行相应的处理,开发人员可以通过注解在不改变原有代码和逻辑的情况下,在源代码中嵌入补充的信息。

spring 从2.5 版本开始提供了对注解技术的全面支持,我们可以实现自动装配,简化spring的xml配置。

 什么是注解 他是代码中的一种特殊标记。

添加扫包即可

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <context:component-scan base-package="org.example.bean.bo"/>
  7. </beans>

 ​

常用注解:

@Component 该注解用于描述spring中的bean,他是一个泛化的概念,仅仅表示容器中的一个组件,并且可以作用在应用的任何层次,serice,dao等。使用时标识在相应类上即可。

@Repository

用于将数据访问层Dao 层的类标识为spring中的bean 功能和@component 相似。

@Service 该注解主要用于放在serice 曾 用于标识 业务曾的bean 和component 相似。

@Controller 用于springmvc 中控制层的标识,和component 相同。

@Autowired 注入

1.属性注入

2.set注入

3.构造方法注入

4.形参注入

只支持 构造方法上。

5.只有构造函数,无注解

只有一个参数时,默认不加注解也支持。

6.autowired注解 和qualifier注解联合 指定对应名称注入

@Resouece 注入

全注解开发:

手写IOC

实现细节:

AOP

代理模式:23种代理模式之一,属于结构性模式,他的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再直接调用目标方法,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中抽离出来----解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

  1. /**
  2. * @Author liu qi
  3. * @Description TODO
  4. * @Date 2023/2/27 21:23
  5. */
  6. public class AnnoApplicationContextImpl implements IApplicationContext {
  7. private Map<Class, Object> beanFactory = new HashMap<>();
  8. private String rootPath;
  9. @Override
  10. public Object getBean(Class clazz) {
  11. return beanFactory.get(clazz);
  12. }
  13. /**
  14. * 基础路径 做扫描包的功能
  15. *
  16. * @param basePackagePath
  17. */
  18. public AnnoApplicationContextImpl(String basePackagePath) {
  19. try {
  20. // . 替换成\
  21. String packagePath = basePackagePath.replaceAll("\\.", "\\\\");
  22. Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packagePath);
  23. while (urls.hasMoreElements()) {
  24. URL url = urls.nextElement();
  25. String filePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8);
  26. rootPath = filePath.substring(0, filePath.length() - packagePath.length());
  27. loadClass(new File(filePath));
  28. }
  29. loadDi();
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. private void loadDi() throws IllegalAccessException {
  35. // 1.从beanFactory中获取已经注入的bean
  36. Set<Map.Entry<Class, Object>> entries = beanFactory.entrySet();
  37. for (Map.Entry<Class, Object> entry : entries) {
  38. Object obj = entry.getValue();
  39. Class<?> aClass = obj.getClass();
  40. // 获取所有的属性
  41. Field[] declaredFields = aClass.getDeclaredFields();
  42. for (Field field : declaredFields) {
  43. Di annotation = field.getAnnotation(Di.class);
  44. if (annotation != null) {
  45. // 从beanFFactory 中获取值
  46. field.setAccessible(true);
  47. field.set(obj, beanFactory.get(field.getType()));
  48. }
  49. }
  50. }
  51. }
  52. /**
  53. * 加载类文件
  54. *
  55. * @param file
  56. */
  57. private void loadClass(File file) {
  58. //1.判断文件是否时文件夹
  59. if (file.isDirectory()) {
  60. File[] childFile = file.listFiles();
  61. //2.判断文件夹是否为空
  62. if (childFile == null || childFile.length == 0) {
  63. return;
  64. }
  65. //3.不为空 遍历文件内容
  66. for (File f : childFile) {
  67. // 4.判断文件是否时文件夹
  68. if (f.isDirectory()) {
  69. loadClass(f);
  70. } else {
  71. // 5.判断是否时class文件
  72. String path = f.getAbsolutePath().substring(rootPath.length() - 1);
  73. if (path.endsWith(".class")) {
  74. try {
  75. // 获取类的全路径
  76. String allPath = path.replaceAll("\\\\", ".").replace(".class", "");
  77. // 5.1判断是否时接口,接口不进行实例化
  78. Class clazz = Class.forName(allPath);
  79. if (!clazz.isInterface()) {
  80. // 5.2 判断是否带我们标注的注解
  81. Annotation annotation = clazz.getAnnotation(Bean.class);
  82. if (annotation != null) {
  83. // 6进行实例化
  84. Object bean = clazz.getConstructor().newInstance();
  85. // 6.1 判断bean是否有接口 如果有默认筛入一个
  86. if (clazz.getInterfaces().length > 0) {
  87. beanFactory.put(clazz.getInterfaces()[0], bean);
  88. } else {
  89. beanFactory.put(clazz, bean);
  90. }
  91. }
  92. }
  93. } catch (ClassNotFoundException e) {
  94. throw new RuntimeException(e);
  95. } catch (InvocationTargetException e) {
  96. throw new RuntimeException(e);
  97. } catch (InstantiationException e) {
  98. throw new RuntimeException(e);
  99. } catch (IllegalAccessException e) {
  100. throw new RuntimeException(e);
  101. } catch (NoSuchMethodException e) {
  102. throw new RuntimeException(e);
  103. }
  104. }
  105. }
  106. }
  107. }
  108. }
  109. }

静态代理:引入目标对象,通过接口包装目标对象的接口,达到静态代理效果。耦合性差,重复性代码多,灵活性差。如想调用app 对象的 add()方法

但是想在 add() 方法前后执行其他操作。就可以 写一个代理类 如appProxy 里面有addProxy (。。。app.add() ...)方法.。

动态代理测试:不必想静态代理一样只针对一个 类。

public class ProxyFactory { private Object target; public ProxyFactory(Object target) { this.target = target; } public Object getTarget() { ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); InvocationHandler invocationHandler = (proxy, method, args) -> { System.out.println("代理执行前"); Object invoke = method.invoke(target, args); System.out.println("代理执行后"); return invoke; }; return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); } }

动态代理分类: jdk动态代理,cglib动态代理。

有接口使用jdk动态代理,生成接口实现类。无接口使用cglib动态代理。

aop 切入点扫描格式

常用通知写法:

切入点可重入性:

在同一个切面中直接引入切点方法即可。

不同切面中引用,需要通过全路径名称引用。包名+类名+方法名称

jdbcTemplate 跳过。

spring Test 整合 junit 加载配置文件 跳过

事务:

资源 访问:

数据校验:Validation

提前编译AOT

下载graalvm

认真研究

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/327860
推荐阅读
相关标签
  

闽ICP备14008679号