我亏一点 - SpringBean
type: channel
link: https://www.000081.xyz/index.php/tag/SpringBean/
items: Java Spring IoC整体流程总结
items: Java Spring 生命周期
items: Java Spring Bean工厂后处理器
items: Java Spring Bean实例化的基本流程
items: Java Spring 配置非自定义Bean
items: Java Spring 获取Bean的三种方式
items: Java Spring beans的profile属性切换环境
items: Java Spring 命名空间
items: Java Spring 自动装配
items: Java 基于xml的Spring应用

Java Spring IoC整体流程总结
type: item
date: 2023-03-04T09:08:00+00:00
description: AI摘要 本文总结了Java Spring IoC的整体流程，重点涵盖了Spring Bean的基本实例化过程、BeanFactory后处理器的执行逻辑以及Bean生命周期的各个阶段。通过对核心环节的梳理，清晰展示了Spring容器管理Bean的完整机制。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring IoC整体流程总结1. 整体流程2. SpringBean基本实例化过程3. BeanFactory后处理器过程4. Bean生命周期阶段

Java Spring 生命周期
type: item
date: 2023-03-04T07:20:00+00:00
description: AI摘要 Spring Bean生命周期分为实例化、初始化和完成阶段。实例化后，在初始化阶段进行属性填充、Aware接口注入及BeanPostProcessor回调。针对循环依赖，Spring通过三级缓存机制解决。最终，完整Bean存入单例池完成生命周期。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring 生命周期1. 概述Spring Bean的生命周期是从 Bean 实例化之后，即通过反射创建出对象之后，到Bean成为一个完整对象，最终存储到单例池中，这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段:Bean的实例化阶段: Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是sinaleton的是否不是延迟加载的，是否不是FactoryBean等，最终将一个普通的singleton的Bean通过反射进行实例化;Bean的初始化阶段: Bean创建之后还仅仅是个"半成品”，还需要对Bean实例的属性进行填充、执行一些Aware接口方法、执行BeanPostProcessor方法、执行InitializingBean接口的初始化方法、执行自定义初始化init方法等。该阶段是Spring最具技术含量和复杂度的阶段，Aop增强功能，后面要学习的Spring的注解功能等spring高频面试题Bean的循环引用问题都是在这个阶段体现的:Bean的完成阶段: 经过初始化阶段，Bean就成为了一个完整的Spring Bean，被存储到单例池singletonObjects中去了，即完成了Spring Bean的整个生命周期2. 初始化阶段2.1 Bean的初始化阶段涉及过程Spring Bean的初始化过程涉及如下几个过程Bean实例的属性填充Aware接口属性注入BeanPostProcessor的before()方法回调InitializingBean接口的初始化方法回调自定义初始化方法init回调BeanPostProcessor的after()方法回调2.2 Bean实例属性填充Spring在进行属性注入时，会分为如下几种情况:注入普通属性，String、int或存储基本类型的集合时，直接通过set方法的反射设置进去;注入单向对象引用属性时，从容器中getBean获取后通过set方法反射设置进去，如果容器中没有，则先创建被注入对象Bean实例(完成整个生命周期)后，在进行注入操作;注入双向对象引用属性时，就比较复杂了，涉及了循环引用(循环依赖)问题2.2.1 propertyValuesBeanDefinition 中有对当前Bean实体的注入信息通过属性propertyValues进行了存储PersonDao.javapackage org.example; public interface PersonDao { }UserDao.javapackage org.example; public interface UserDao { }UserDaoImpl.javapackage org.example; public class UserDaoImpl implements UserDao { }PersonDaoImpl.javapackage org.example; public class PersonDaoImpl implements PersonDao{ public String getName() { return name; } public void setName(String name) { this.name = name; } public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } private String name; private UserDao userDao; } beans.xml<bean class="org.example.UserDaoImpl" id="userDao"/> <bean class="org.example.PersonDaoImpl" id="personDao"> <property name="userDao" ref="userDao"/> <property name="name" value="名字"/> </bean>主函数调用ClassPathXmlApplicationContext applicationContext = new ClassPathXml…

Java Spring Bean工厂后处理器
type: item
date: 2023-03-02T08:21:00+00:00
description: AI摘要 本文介绍了Spring两大核心扩展点：BeanFactoryPostProcessor用于在Bean实例化前动态修改或注册BeanDefinition；BeanPostProcessor则在Bean初始化前后介入，常用于属性填充或通过动态代理实现功能增强。两者为开发者提供了介入Bean生命周期的灵活机制。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring Bean工厂后处理器Spring的后处理器是Spring对外开发的重要扩展点，允许我们介入到Bean的整个实例化流程中来，以达到动态注册BeanDefinition，动态修改BeanDefinition，以及动态修改Bean的作用。Spring主要有两种后处理器:BeanFactoryPostProcessor: Bean工厂后处理器，在BeanDefinitionMap填充完毕，Bean实例化之前执行；BeanPostProcessor: Bean后处理器，一般在Bean实例化之后，填充到单例池singletonObjects之前执行。1. BeanFactoryPostProcessor1.1 快速入门BeanFactoryPostProcessor是一个接口规范，实现了该接口的类只要交由Spring容器管理的话，那么Spring就会回调该接口的方法，用于对BeanDefinition注册和修改的功能。实例化流程MyBeanFactoryPostProcessor.javapackage processor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { System.out.println("beanDefinitionMap填充完毕后回调该方法"); } } beans.xml<bean class="processor.MyBeanFactoryPostProcessor"/>主函数断点调试public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); }执行结果beanDefinitionMap填充完毕后回调该方法1.2 强制修改BeanDefinition其他设置基于上文MyBeanFactoryPostProcessor.javapublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { System.out.println("beanDefinitionMap填充完毕后回调该方法"); BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition("userService"); beanDefinition.setBeanClassName("org.example.UserDaoImpl"); } }主函数调用public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml…

Java Spring Bean实例化的基本流程
type: item
date: 2023-02-28T03:00:00+00:00
description: AI摘要 Spring Bean实例化流程如下：首先解析配置文件，将Bean信息封装为BeanDefinition并存入beanDefinitionMap；随后容器遍历该Map，通过反射创建Bean实例并存入singletonObjects集合；最终调用getBean方法时，直接从singletonObjects中获取并返回对应的Bean实例。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring Bean实例化的基本流程Spring容器在进行初始化时，会将xml配置的<bean>的信息封装成一个BeanDefinition对象，所有的BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去，Spring框架在对该Map进行遍历，使用反射创建Bean实例对象，创建好的Bean对象存储在一个名为singletonObjects的Map集合中，当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。流程：加载xml配置文件，解析获取配置中的每个<bean>的信息，封装成一个个的BeanDefinition对象将BeanDefinition存储在一个名为beanDefinitionMap的Map<String,BeanDefinition>中;ApplicationContext底层遍历beanDefinitionMap，创建Bean实例对象 创建好的Bean实例对象，被存储到一个名为singletonObjects的Map<String,Object>中;当执行applicationContext.getBean(beanName)时，从singletonObjects去匹配Bean实例返回beans.xml <bean class="org.example.UserDaoImpl" id="userDao"/> <bean class="org.example.UserServiceImpl" id="userService"/>主函数断点调试运行 public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); }Bean信息定义对象-BeanDefinitionBeanDefinition.class// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.beans.factory.config; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.MutablePropertyValues; import org.springframework.core.AttributeAccessor; import org.springframework.core.ResolvableType; import org.springframework.lang.Nullable; public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { String SCOPE_SINGLETON = "singleton"; String SCOPE_PROTOTYPE = "prototype"; int ROLE_APPLICATION = 0; int ROLE_SUPPORT = 1; int ROLE_INFRASTRUCTURE = 2; void setParentName(@Nullable String var1); @Nullable String getParentName(); void setBeanClassName(@Nullable String var1); @Nullable String getBeanClassName(); void setScope(@Nullable String var1); @Nullable String getScope(); void setLazyInit(boolean var1); boolean isLazyInit(); void setDependsOn…

Java Spring 配置非自定义Bean
type: item
date: 2023-02-27T08:52:00+00:00
description: AI摘要 本文介绍了如何在Spring中配置非自定义Bean（第三方类）。通过Druid数据源、JDBC连接、日期对象及MyBatis的SqlSessionFactory等实例，展示了利用无参构造、静态工厂方法及实例工厂方法三种方式，实现第三方Bean的实例化与属性注入，从而将其纳入Spring容器管理。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring 配置非自定义Bean0.介绍实际开发中会使用第三方jar包中的功能类，这些Bean要想让Spring进行管理，也需要对其进行配置两个问题：被配置的Bean实例化方式是什么被配置的Bean是否需要注入必要属性1.配置Druid数据源交由Spring管理maven配置文件导入相应jar包pom.xml <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency>beans.xml <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/java"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean>主函数调用 public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); Object dataSource = applicationContext.getBean("dataSource"); System.out.println(dataSource); }运行结果{ CreateTime:"2023-02-26 17:23:51", ActiveCount:0, PoolingCount:0, CreateCount:0, DestroyCount:0, CloseCount:0, ConnectCount:0, Connections:[ ] }2.配置Connection交由Spring管理Connection的产生是通过DriverManager的静态方法getConnection获取的，所以我们要用静态工厂的方式配置beans.xml（getConnection报红不用管） <bean id="connection" class="java.sql.DriverManager" factory-method="getConnection" scope="prototype"> <constructor-arg name="url" value="jdbc:mysql://localhost:3306/java"/> <constructor-arg name="user" value="root"/> <constructor-arg name="password" value="root"/> </bean>主函数调用 public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); Object connection = applicationContext.getBean("connection"); System.out.println(connection);; }执行结果（报错不用管，看到有类字节码地址输出即可）com.mysql.jdbc.JDBC4Connection@42a15bdc3.配置日期对象交由Spring管理原生使用日期对象 Sim…

Java Spring 获取Bean的三种方式
type: item
date: 2023-02-26T09:03:00+00:00
description: AI摘要 本文介绍了在Java Spring框架中获取Bean的三种主要方式：一是通过ApplicationContextAware接口手动获取；二是通过注解@Autowired或@Resource进行自动注入；三是利用BeanFactory或ApplicationContext直接从容器中根据名称或类型检索Bean。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring 获取Bean的三种方式

Java Spring beans的profile属性切换环境
type: item
date: 2023-02-26T08:16:00+00:00
description: AI摘要 Spring通过在``标签中使用`profile`属性，可实现不同环境下的Bean配置切换。激活环境可通过命令行参数`-Dspring.profiles.active`或代码中设置`System.setProperty`实现，从而灵活加载特定环境所需的Bean。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring beans的profile属性切换环境<beans>标签，除了经常用的作为根标签外，还可以嵌套在根标签内，使用profile属性切换开发环境可以使用以下两种方式指定被激活的环境（dev为环境名）：使用命令行动态参数，虚拟机参数位置加载 -Dspring.profiles.active=dev使用代码的方式设置环境变量System.setProperty("spring.profiles.active","dev")beans.xml <bean class="org.example.UserDaoImpl" id="userDao"/> <bean class="org.example.UserServiceImpl" id="userService"/> <beans profile="dev"> <bean id="userService1" class="org.example.UserServiceImpl"/> </beans> <beans profile="test"> <bean id="userDao1" class="org.example.UserDaoImpl"/> </beans>主函数调用 public static void main(String[] args) { // 指定环境 System.setProperty("spring.profiles.active","dev"); ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); System.out.println(((UserService) applicationContext.getBean("userService"))); System.out.println(((UserDao) applicationContext.getBean("userDao"))); System.out.println(((UserService) applicationContext.getBean("userService1"))); System.out.println(((UserDao) applicationContext.getBean("userDao1"))); }执行结果org.example.UserServiceImpl@589b3632 org.example.UserDaoImpl@45f45fa1 org.example.UserServiceImpl@4c6e276e Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userDao1' available

Java Spring 命名空间
type: item
date: 2023-02-26T07:40:00+00:00
description: AI摘要 本文介绍了Java Spring配置文件中的命名空间使用方法，包括默认命名空间及自定义命名空间的创建。同时讲解了通过``标签实现配置文件的模块化拆分与导入，以及利用``标签为Bean设置别名，从而提升配置的灵活性与可维护性。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring 命名空间Spring的默认标签用到的是Spring的默认命名空间beans.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-3.0.xsd"> </beans>该命名空间约束下的默认标签如下：创建命名空间创建名为context的命名空间beans.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd " > <context:property-placeholder/> </beans>import引入其他配置文件<import>标签，用于导入其他配置文件，项目变大后，就会导致一个配置文件内容过多，可以将一个配置文件根据业务某块进行拆分，拆分后，最终通过<import>标签导入到一个主配置文件中，项目加载主配置文件就连同<import>导入的文件一并加载了<import resource="classpath:beans.xml"></import>alias指定Bean别名断点调试中，BeanFactory下aliasMap中保存了alias指定的别名，并不会影响bean中name标签指定的值，但是也能通过alias指定的别名进行获取bean<bean class="org.example.UserDaoImpl" id="userDao"/> <bean class="org.example.UserServiceImpl" id="userService"/> <alias name="userDao" alias="dao"></alias> <alias name="userService" alias="service"></alias>

Java Spring 自动装配
type: item
date: 2023-02-25T12:52:00+00:00
description: AI摘要 Spring框架支持通过``标签的`autowire`属性实现自动装配。`byName`根据属性名匹配Bean的id，`byType`根据类型匹配。若使用`byType`时容器中存在多个同类型Bean，系统将抛出异常，无法完成自动装配。 此内容根据文章生成，仅用于文章内容的解释与总结 Java Spring 自动装配如果被注入的属性类型是Bean引用的话，那么可以在<bean>标签中使用autowire属性去配置自动注入方式，属性值有两个byName：通过属性名自动装配，即去匹配setXxx与id="xxx"(name="xxx")是否一致；byType：通过Bean的类型从容器中匹配，匹配出多个相同Bean类型，报错。beans.xml<bean class="org.example.UserDaoImpl" id="userDao"/> <bean class="org.example.UserServiceImpl" id="userService" autowire="byName"/> <bean class="org.example.UserServiceImpl" id="userService1" autowire="byType"/>UserServicepublic interface UserService { public void show(); }UserServiceImplpublic class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao){ this.userDao = userDao; } @Override public void show() { System.out.println(userDao); } }主函数调用public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); ((UserService) applicationContext.getBean("userService")).show(); ((UserService) applicationContext.getBean("userService1")).show(); }执行结果org.example.UserDaoImpl@1f0f1111 org.example.UserDaoImpl@1f0f1111如果xml文件自动装配中有多个同类型的bean容器将会报错例如：<bean class="org.example.UserDaoImpl" id="userDao"/> <bean class="org.example.UserDaoImpl" id="userDao1"/> <bean class="org.example.UserServiceImpl" id="userService" autowire="byName"/> <bean class="org.example.UserServiceImpl" id="userService1" autowire="byType"/>IDEA报错提示无法自动装配。存在多个 'UserDao' 类型的 Bean。Bean: userDao1,userDao。属性: 'userDao'运行结果提示警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService1' defined in class path resource [beans.xml]: Unsatisfied dependency expressed through bean property 'userDao'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.example.UserDao' ava…

Java 基于xml的Spring应用
type: item
date: 2023-02-22T13:15:00+00:00
description: AI摘要 本文介绍了基于XML的Spring应用开发，涵盖了Bean的基础配置、作用范围（singleton/prototype）、延迟加载、生命周期方法（init/destroy）、实例化方式（构造、工厂、FactoryBean）以及依赖注入（List、Set、Map等集合类型）的详细配置方法。 此内容根据文章生成，仅用于文章内容的解释与总结 Java 基于xml的Spring应用1.SpringBean 的配置解析Spring开发中主要是对Bean的配置，Bean的常用配置一览如下： 1.Bean的基础配置配置UserDaoImpl由Spring容器负责管理<bean id="userDao" class="org.example.UserDaoImpl"></bean>此时存储到Spring容器（singleObjects单例池）中的Bean的beanName是userDao，值是UserDaoImpl对象，可以根据beanName获取Bean实例applicationContext.getBean("userDao")如果不配置id，则Spring会把当前Bean实例的全限定名作为beanNamepublic static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); UserDao bean = (UserDao) applicationContext.getBean("org.example.UserDaoImpl"); System.out.println(bean); }如果配置了id，便不能在使用Bean实例的全限定名进行获取，例如：applicationContext.getBean("org.example.UserDaoImpl");配置别名，配置别名后可以使用别名获得Bean对象实例<bean id="userDao" name="aaa,bbb" class="org.example.UserDaoImpl"></bean>2.SpringBean的配置详解1.Bean的范围配置默认情况下，单纯的Spring环境Bean的作用范围有两个：Singleton和Prototypesingleton：单例，默认值，Spring容器创建的时候，就会进行Bean的实例化，并且存储到容器内部的单例池中，每次getBean时都是从单例池中获取相同的Bean实例<bean id="userDao" class="org.example.UserDaoImpl" scope="singleton"></bean>prototype：原型，Spring容器初始化时不会创建Bean实例，只有调用getBean时才会实例化Bean，每次getBean都会创建一个新的Bean实例<bean id="userDao" class="org.example.UserDaoImpl" scope="prototype"></bean>如果是spring-webmvc的情况下，还会增加两个作用范围：request和sessionmaven导包<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.7</version> </dependency>request：将创建的对象放在request域当做<bean id="userDao" class="org.example.UserDaoImpl" scope="request"></bean>session：将创建的对象放在session域当做<bean id="userDao" class="org.example.UserDaoImpl" scope="session"></bean>2.Bean的延迟加载当lazy-init设置为true时为延迟加载，也就是当Spring容器创建的时候，不会立即创建Bean实例，等待用到时在创建Bean实例并且存储到单例池中去，后续在使用该Bean直接冲单例池获取，本质上该Bean还是单例的，只对scope设置为singleton的Bean起作用，对prototype无效，对BeanFactory作为容器也无效<bean id="userDao" class="org.example.UserDaoImpl" lazy-init="true"></bean>3.Bean的初始化方法和销毁方法init-method…