我亏一点 - BeanFactory
type: channel
link: https://blog.996818.xyz/index.php/tag/BeanFactory
items: Java Spring IoC整体流程总结
items: Java Spring 生命周期
items: Java Spring Bean工厂后处理器
items: Java Spring Bean实例化的基本流程
items: Java Spring 配置非自定义Bean
items: Java Spring 自动装配
items: Java 基于xml的Spring应用
items: Java BeanFactory与ApplicationContext的关系与继承体系
items: Java ApplicationContext
items: Java BeanFactory

Java Spring IoC整体流程总结
type: item
date: 2023-03-04T09:08:00+00:00
description: Java Spring IoC整体流程总结1. 整体流程2. SpringBean基本实例化过程3. BeanFactory后处理器过程4. Bean生命周期阶段

Java Spring 生命周期
type: item
date: 2023-03-04T07:20:00+00:00
description: 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 ClassPathXmlApplicationContext("beans.xml");例如PersonDao的属性信息如下:2.2.2 循环引用多个实体之间相互依赖并形成闭环的情况就叫做”循环依赖”，也叫做”循环引用。死循环原理图UserDaoImpl.javapackage org.example; public class…

Java Spring Bean工厂后处理器
type: item
date: 2023-03-02T08:21:00+00:00
description: 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"); Object userService = applicationContext.getBean("userService"); System.out.println(userService); }输出结果beanDefinitionMap填充完毕后回调该方法 org.example.UserDaoImpl@3c875211.3 动态注入BeanDefini…

Java Spring Bean实例化的基本流程
type: item
date: 2023-02-28T03:00:00+00:00
description: 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(@Nullable String... var1); @Nullable String[] getDependsOn(); void setAutowireCandidate(boolean var1); boolean isAutowireCandidate(); void setPrimary(boolean var1); boolean isPrimary(); void setFac…

Java Spring 配置非自定义Bean
type: item
date: 2023-02-27T08:52:00+00:00
description: 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管理原生使用日期对象 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = simpleDateFormat.parse("2023-08-27 12:00:00"); System.out.println(date);结果输出Sun Aug 27 1…

Java Spring 自动装配
type: item
date: 2023-02-25T12:52:00+00:00
description: 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' available: expected single matching bean but found 2: userDao,userDao1 Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependen…

Java 基于xml的Spring应用
type: item
date: 2023-02-22T13:15:00+00:00
description: 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：初始化时运行方法destroy-method：销毁时运行方法，单例模式容器必须显示关闭才会执行这个方法，否则不会执行关闭，又因为ApplicationContext的接口没有关闭容器的方法，所以类型需要使用ClassPathXmlApplicationContext，才有close显式关闭容器，如果不使用显式关闭，则有可能不会执行销毁方法，例如…

Java BeanFactory与ApplicationContext的关系与继承体系
type: item
date: 2023-02-22T03:14:00+00:00
description: BeanFactory与ApplicationContext的关系BeanFactory是Spring的早期接口，成为Spring的Bean工厂，ApplicationContext是后期更高级接口，称之为Spring容器；ApplicationContext在BeanFactory基础上对功能进行了扩展，例如：监听功能、国际化功能等。BeanFactory的API更偏向于底层，ApplicationContext的API大多数是对这些底层API的封装Bean创建的主要逻辑和功能都被封装在BeanFactory中，ApplicationContext不仅继承了BeanFactory，而且ApplicationContext内部还维护着BeanFactory的引用，所以ApplicationContext与BeanFactory既有继承关系，又有融合关系Bean的初始化时机不同，原始BeanFactory是在首次调用getBean时才进行Bean的创建，而ApplicationContext则是配置文件加载，容器一创建就将Bean都实例化初始化好BeanFactorypublic static void main(String[] args) { // 创建工厂对象 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); // 创建一个读取器（xml文件） XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); // 读取配置文件给工厂 reader.loadBeanDefinitions("beans.xml"); // 根据id获取bean实例对象，Bean在此时创建对象 UserService userService = (UserService) beanFactory.getBean("userService"); System.out.println(userService); }ApplicationContextpublic static void main(String[] args) { // 读取配置文件的时候便已经实例化初始化完成 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); System.out.println(userService); }BeanFactory与ApplicationContext的继承体系BeanFactor的继承体系BeanFactory是核心接口，项目运行过程中肯定有具体实现参与，这个具体实现就是DefaultListtableBeanFactory，而ApplicationContext内部维护的BeanFactory的实现类也是它ApplicationContext的继承体系只在Spring基础环境下，即只导入spring-context坐标时，此时ApplicationContext的继承体系 只在Spring基础环境下，常用的三个ApplicationContext作用如下：

Java ApplicationContext
type: item
date: 2023-02-22T02:30:00+00:00
description: Java ApplicationContext快速入门ApplicationContext成为Spring容器，内部封装了BeanFactory，笔BeanFactory功能更丰富更强大，使用ApplicationContext进行开发式，xml配置文件的名称习惯写成applicationContent.xml1.使用ApplicationContext调用BeanFactory基础配置可看上一篇文章 点我跳转public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); System.out.println(userService); }运行结果：BeanFactory去调用该方法 从容器中获得userDao设置到此处org.example.UserDaoImpl@1e730495 org.example.UserServiceImpl@318ba8c8

Java BeanFactory
type: item
date: 2023-02-22T01:34:00+00:00
description: Java BeanFactory快速入门Ioc思想实现1.创建普通的Maven项目2.在pom.xml文件中的project标签内导入Spring的jar包<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ...... <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.7</version> </dependency> </dependencies> </project>3.创建UserService接口4.创建UserServiceImpl类，并且继承UserService接口5.在resources中创建beans.xml文件，并且配置bean <?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="userService" class="org.example.UserServiceImpl"></bean> </beans>6.主函数运行 public static void main(String[] args) { // 创建工厂对象 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); // 创建一个读取器（xml文件） XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); // 读取配置文件给工厂 reader.loadBeanDefinitions("beans.xml"); // 根据id获取bean实例对象 UserService userService = (UserService) beanFactory.getBean("userService"); System.out.println(userService); }DI思想实现，依赖注入1.创建UserDao接口和UserDaoIpml类，类继承UserDao接口2.在UserServiceImpl类中新建一个set方法，用于接受设置注入的对象 public class UserServiceImpl implements UserService{ // BeanFactory去调用该方法 从容器中获得userDao设置到此处 public void setUserDao(UserDao userDao){ System.out.println("BeanFactory去调用该方法 从容器中获得userDao设置到此处" + userDao); } }3.配置beans.xml文件，在bean标签中添加property标签实现依赖注入 <?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="userService" class="org.example.UserServiceImpl"> <pr…