Java Study!! - Spring6
type: channel
link: https://kaijavademo.top/category/Spring6/
description: 微服务核心Sping6
items: Spring笔记：事务|Resource接口|Validation校验
items: Spring笔记：面向切面AOP的两种实现
items: Spring笔记：实现手写核心IoC步骤
items: Spring笔记：依赖注入|基于XML和注解方式管理Bean到全注解开发

Spring笔记：事务|Resource接口|Validation校验
type: item
date: 2023-08-02T06:38:00+00:00
description: 笔记基于Spring6演示CURD操作，不同于以前JDBC，现在的事务操作时基于注解和Spring技术完成之前有过对于JDBC的介绍和工具类的封装JDBC工具类封装准备工作：父工程中添加依赖<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>6.0.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.15</version> </dependency> </dependencies>创建配置文件jdbc.propertiesjdbc.user=root jdbc.password=abc123 jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false jdbc.driver=com.mysql.cj.jdbc.Driver在新建的模块类路径下添加bean.xml，调整配置信息引入外部配置文件，创建数据源对象创建 [label color="red"]jdbcTemplate[/label] 对象，注入数据源<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="${jdbc.url}"></property> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="username" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="druidDataSource"></property> </bean> </beans>在JDBCTemplateTest 测试类中完成数据库的CRUD，通过整合Junit5通过注解完成xml文件的读取和对象jdbcTemplate的属性注入。通过@SpringJUnitConfig(locations = "classpath:beans.xml") 代替 ApplicationContext context = new ClassPathXmlApplicationContext(".xml"); …

Spring笔记：面向切面AOP的两种实现
type: item
date: 2023-08-01T15:04:00+00:00
description: spring笔记，有关spring中另一个核心技术AOP的理解。涉及到代理设计模式(后面会更新)静态代理中由于将某些代码写死，降低了一定的扩展性，所以说后来产生了动态代理，而AOP的底层就是基于动态代理.关于静态代理不做过多赘述，笔记中以AOP的实现为主延伸动态代理。动态代理public class ProxyFactory //目标对象传递CalculatorImpl private Object target; //把目标对象传递进来 public ProxyFactory(Object target) { this.target = target; } //创建一个方法，返回代理对象（动态） public Object getProxy() { //动态代理创建对象 /* Proxy.newProxyInstance()方法有三个参数 参数一：ClassLoader:加载动态生成代理类的类加载器 参数二：Class[] interfaces:目标对象实现所有接口class类型数组(数组结构) 参数三：InvocationHandler:设置代理对象实现目标对象目标方法的过程 */ //参数一：ClassLoader:加载动态生成代理类的类加载器 ClassLoader classLoader = target.getClass().getClassLoader(); //参数二：Class[] interfaces:目标对象实现所有接口class类型数组(数组结构) Class<?>[] interfaces = target.getClass().getInterfaces(); //参数三：InvocationHandler:设置代理对象实现目标对象目标方法的过程 InvocationHandler invocationHandler = new InvocationHandler() { //InvocationHandler是一个接口，使用匿名内部类来实现invoke方法 //参数一：代理对象 //参数二：需要重写的目标对象的方法 //参数三：method方法里面的参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //方法调用之前做输出 System.out.println("[动态代理][日志] " + method.getName() + "，参数：" + Arrays.toString(args)); //调用目标的方法 Object result = method.invoke(target, args); //方法调用之后做个输出 System.out.println("[动态代理][日志] " + method.getName() + "，结果：" + result); return result; } }; return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); } } AOPAOP是一种设计思想，它以通过预编译的方式和运行期动态代理方式实现，在不修改原代码的情况下，给程序动态统一添加额外功能的技术。使得各个业务逻辑各部分之间耦合度降低。相关知识点横切关注点：我们在方法中抽取一些同样一类的非核心业务，比如：用户验证、事务处理通知(增强)：增强的功能，比如：用户的安全校验，事务，日志...通过方法进行实现的叫做通知方法。动态代理分类：JDK的动态代理(有接口的情况。生成一个接口实现类的代理对象，代理对象和目标对象实现了相同的接口)和cglib的动态代理(没有接口的情况。生成一个子类的代理对象，继承被代理目标类)AspectJ：是AOP框架，Spring只是借用了AspectJ中的注解实现了AOP功能。注解方式实现AOP引入AOP相关依赖父工程中添加依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>6.0.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>6.0.2</version> </dependency> 子工程resources文件中添加xml文件，调整配置信息，开启组件扫描<?xml version="1.0"…

Spring笔记：实现手写核心IoC步骤
type: item
date: 2023-07-31T14:29:00+00:00
description: 通过手写代码，写出spring框架最核心的部分之前在JavaWeb中的学习里一段初步手写IoC可供参考和跳转初步学习实现过程创建子模块()引入依赖创建测试类和接口（service dao）创建(手写)两个注解，实现IoC功能@Bean 创建对象@Di 属性注入创建Bean容器接口 [label color="blue"]ApplicationContext[/label] ,定义方法，返回对象实现Bean容器接口，实现类中功能返回对象根据包的扫描规则，加载bean扫描规则:比如包是com.atguigu扫描com.atguigu这个包，和他的子包里面的所有类，扫描这个上面是否有@Bean注解，如果有，那就把这个类通过反射进行实例化。准备工作简单来说就是通过手写代码的方式实现两个注解(对应第三步)创建两个注解类，配置方式如下创建bean容器接口并实现(第四步)实现容器接口(第五步：实现第一个注解)@Bean创建对象我们创建一个集合，重写接口中的方法，通过getBean方法，在集合中获取，返回我们需要的对应类的对象。在有参数的构造当中，我们需要编写对应的扫描规则。首先我们需要获取对应包的绝对路径，同时添加一个简化路径的变量rootPath方便后面扫描，根据路径添加一个扫描包的方法 [label color="blue"]loadBean[/label] 随后我们具体实现扫描包的方法。public class AnnotationApplicationContext implements ApplicationContext { //创建map集合，放bean实例对象 private Map<Class, Object> beanFactory = new HashMap<>(); //简化路径 private static String rootPath; //此方法用于返回我们创建的对象 @Override public Object getBean(Class clazz) { //根据key返回对象 return beanFactory.get(clazz); } //设置包的扫描规则 //当前包及其子包里面，哪个类有@Bean注解，把这个类通过反射进行实例化 //创建有参数构造，传递包的路径basePackage，设置扫描规则 //public AnnotationApplicationContext(String basePackage) throws IOException { public static void pathdemo1(String basePackage) { try { //设置包的扫描规则 com.atguigu.spring6 //找到这个包所在的路径，找到绝对路径，看一下文件夹中是否有子文件夹和文件 //1.把.替换成\ String packagePath = basePackage.replaceAll("\\.", "\\\\"); //2.获取包的绝对路径 Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packagePath); while (urls.hasMoreElements()) { //遍历，得到里面的每一个具体值 URL url = urls.nextElement(); //转码 String filePath = URLDecoder.decode(url.getFile(), "utf-8"); //获取包前面的路径部分，用作字符串截取 rootPath = filePath.substring(0, filePath.length() - packagePath.length()); //根据路径进行包扫描过程 loadBean(new File(filePath)); } } catch (IOException e) { throw new RuntimeException(e); } } public static void main(String[] args) { pathdemo1("com.atguigu"); } }@Bean创建对象实现loadBean方法的大致思路如下 //包扫描过程，实例化 private static void loadBean(File file) { //1.判断当前文件是否文件夹 //2.是文件夹，获取文件夹中里面的所有内容 //3.判断文件夹里面内容为空，直接返回 //4.如果文件夹里面不为空，遍历文件夹里面的所有内容 //4.1遍历得到每部分内容file对象，继续判断，如果还是文件夹，递归 //…

Spring笔记：依赖注入|基于XML和注解方式管理Bean到全注解开发
type: item
date: 2023-07-29T11:33:00+00:00
description: 有关Spring6的学习笔记，从配置XML文件到最后使用全注解开发。[note type="primary flat"]IoC 是 Inversion of Control 的简写，译为“控制反转”.是一种设计思想，并不是一种技术。Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化，控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean，它与使用关键字 new 创建的 Java 对象没有任何区别。对象从创建到销毁过程都是通过容器来管理的容器放bean对象，使用map集合，存放方便。在xml配置文件中定义相应的Bean信息BeanDefinition，通过接口BeanDefinitionReader读取加载,放入IoC容器中，存储Bean定义信息。在IoC容器中实例化Bean的定义信息(当然这个信息可以修改)，创建通过BeanFactory工厂(模式) + 反射，目前(实例化)是一个空对象，然后进行初始化才可以使用。通过context.getBean();可以使用。依赖注入：指Spring创建对象的过程中，将对象依赖属性通过配置进行注入依赖注入常见的实现方式包括两种：第一种：set注入第二种：构造注入Bean管理说的是：Bean对象的创建，以及Bean对象中属性的赋值（或者叫做Bean对象之间关系的维护）.[/note]三种方式获取bean对象获取bean对象前的操作省略，无非就是配置spring依赖，读取xml的配置文件方式一：根据id获取bean对象 //1.根据id获取bean对象 User user = (User) context.getBean("user");//括号中加上xml文件中配置的id属性值 System.out.println("1.根据id获取bean:" + user); 方式二：根据类型获取bean对象 //2.根据类型来获取bean对象 User user2 = context.getBean(User.class); System.out.println("2.根据类型获取bean:" + user2); [label color="red"]注意：这种方式获取bean，要求IOC容器中指定类型的bean有且只能有一个[/label] 如果xml配置多个bean，使用这种方式报错。 <bean id="user" class="com.atguigu.sping6.iocxml.User"></bean> <bean id="user1" class="com.atguigu.sping6.iocxml.User"></bean>如果是 [label color="blue"]接口 = 实现类对象[/label] 的形式，根据接口类型可以得到bean对象。如果一个接口有多个实现类，这些实现类都配置了bean，根据接口类型 [label color="red"]不可以[/label] 获取到bean。因为不唯一，一个接口有多个对象。方式三：根据 id + 类型 获取bean对象 //3.根据id和类型获取bean对象 User user3 = context.getBean("user", User.class); System.out.println("3.根据id和类型:" + user3); 依赖注入类有属性，创建对象的过程中，向属性(成员变量)设置值，有两种方法基于set方法完成注入创建类，定义属性，生成属性set方法。准备类：package com.atguigu.sping6.iocxml.di; public class Book { //一会，创建对象中完成属性设置 private String bname; private String author; public Book() { } public Book(String bname, String author) { this.bname = bname; this.author = author; } public static void main(String[] args) { //set方法注入 Book book = new Book(); book.setBname("java"); book.setAuthor("尚硅谷"); //通过构造器方法注入 Book book1 = new Book("C++","尚硅谷"); } /** * 设置 * @param bname */ public void setBname(String bname) { this.bname = bname; } /** * 设置 * @param auth…