BeanDefinition 元信息
属性 (Property) | 说明 |
---|---|
Class | Bean 全类名, 必须是具体类, 不能用抽象类或接口 |
Name | Bean 的名称或者 ID |
Scope | Bean 的作用域 (如: singleton、prototype 等) |
Constructor arguments | Bean 构造器参数 (用于依赖注入) |
Properties | Bean 属性设置 (用于依赖注入) |
Autowiring mode | Bean 自动绑定模式 (如: 通过名称 byName) |
Lazy initialization mode | Bean 延迟初始化模式 (延迟和非延迟) |
initialization method | Bean 初始化回调方法名称 |
Destruction method | Bean 销毁回调方法名称 |
BeanDefinition 构建
通过 BeanDefinitionBuilder
通过 AbstractBeanDefinition 以及派生类
User.class
package org.xiaoge.thinking.in.spring.ioc.overview.domain;/*** @Classname User* @Date 2022/10/17 14:57* @Created by ZhangXiao* @Description TODO*/
public class User {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}
BeanDefinitionCreationDemo.class
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** {@link org.springframework.beans.factory.config.BeanDefinition} 构建示例** @Classname BeanDefinitionCreationDemo* @Date 2022/11/2 16:05* @Created by ZhangXiao* @Description TODO*/
public class BeanDefinitionCreationDemo {public static void main(String[] args) {// 1. 通过 BeanDefinitionBuilder 构建BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);// 通过属性设置beanDefinitionBuilder.addPropertyValue("id", 1).addPropertyValue("name", "xiaoge");// 获取 BeanDefinition 实例BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();// BeanDefinition 并非 Bean 终态, 可以自定义修改// 2. 通过 AbstractBeanDefinition 以及派生类GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();// 设置 Bean 类型genericBeanDefinition.setBeanClass(User.class);// 通过 MutablePropertyValues 批量操作属性MutablePropertyValues propertyValues = new MutablePropertyValues();// propertyValues.addPropertyValue("id", 1);// propertyValues.addPropertyValue("name", "xiaoge");propertyValues.add("id", 1).add("name", "xiaoge");// 通过 set MutablePropertyValues 批量操作属性genericBeanDefinition.setPropertyValues(propertyValues);}}
Bean名称
每个Bean 拥有一个或多个标识符(identifiers) ,这些标识符在Bean 所在的容器必须是唯一的。通常,一个 Bean仅有一个标识符,如果需要额外的,可考虑使用别名(Alias) 来扩充。
在基于XML的配置元信息中,开发人员可用id或者name属性来规定 Bean的标识符。通常Bean 的标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在
name 属性使用半角逗号(“,”)或分号(“;”)来间隔。
Bean 的id 或name属性并非必须制定,如果留空的话,容器会为Bean自动生成一个唯一的名称。Bean的命名尽管没有限制, 不过官方建议采用驼峰的方式,更符合Java的命名约定。
Bean名称生成器(BeanNameGenerator)
由Spring Framework 2.0.3引入,框架内建两种实现:
AnnotationBeanNameGenerator:基于注解扫描的 BeanNameGenerator实现,
起始于SpringFramework 2.5,关联的官方文档:
With component scanning in the classpath,Spring generates bean names for unnamed components,following the rules described earlier: essentially,taking the simple class name and turnined components,following the rules described earlier: essentially,taking the simple class name and turning its initial character to lower-case.However, in the (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved.These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses herre).通过在类路径中扫描component,Spring为未命名的组件生成bean名称,遵循前面描述的规则:实质上,采用简单的类名和翻转的组件,遵循前面描述的规则:实质上,采用简单的类名并将其初始字符改为小写。但是,在(不寻常的)特殊情况下,当有多个字符并且第一个和第二个字符都是大写字母时,原始的大小写将被保留。这些规则与java.beans.Introspector.decapitalize (Spring在这里使用)定义的规则相同。
关于Bean的命名, Bean的命名有两种方式, 一种是Spring容器自动帮你生成, 当你没有设置名称/id的时候, 另一种是自己去定义所需要的名称, 一般XML是自己定义名称, 而注解我们一般很少会自己去定义名称。
Bean别名(Alias)的价值
复用现有的 BeanDefinition
更具有场景化的命名方法,比如:
Bean别名(Alias)的价值
bean-deginitions-context.xml
BeanAliasDemo
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** {@link BeanAliasDemo} 别名示例** @Classname BeanAliasDemo* @Date 2022/11/2 17:02* @Created by ZhangXiao* @Description TODO*/
public class BeanAliasDemo {public static void main(String[] args) {// 配置xml配置文件// 启动spring应用上下文BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-deginitions-context.xml");// 通过id和类型取User user = beanFactory.getBean("user", User.class);// 通过别名 获取 曾用命 user 的 BeanUser xiaogeUser = beanFactory.getBean("xiaoge-user", User.class);System.out.println("xiaogeUser 是否与 user Bean 相同: " + (xiaogeUser == user));}}/*运行结果xiaogeUser 是否与 user Bean 相同: true
*/
BeanDefinition 注册
XML这里就不写了, 主要写注解 和 JavaAPI 方式
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** 注解 BeanDefinition 示例* 1. 通过 @Bean 方式定义* 2. 通过 @Component 方式定义* 3. 通过 @Import 方式定义* Java API 配置元信息* 1. 通过 BeanDefinitionRegistry 方式定义* 2. 通过 BeanDefinitionReaderUtils 方式定义* 3. 通过 AnnotatedBeanDefinitionReader 方式定义** @Classname AnnotationBeanDefinitionDemo* @Date 2022/11/3 9:22* @Created by ZhangXiao* @Description TODO*/
@Import(AnnotationBeanDefinitionDemo.Config.class) // 3. 通过 @Import 方式定义
public class AnnotationBeanDefinitionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 Configuration Class 配置类applicationContext.register(AnnotationBeanDefinitionDemo.class);// 通过 BeanDefinition 注册 API 实现// 1. 命名 Bean 的注册方式registerUserBeanDefinition(applicationContext, "xiaoge-niubi");// 2. 非命名 Bean 的注册方式registerUserBeanDefinition(applicationContext);// 3. 配置类方式AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);annotatedBeanDefinitionReader.register(Config.class);// 启动应用上下文applicationContext.refresh();// 按照类型依赖查找System.out.println("Config 类型的所有 Beans: " + applicationContext.getBeansOfType(Config.class));System.out.println("User 类型的所有 Beans: " + applicationContext.getBeansOfType(User.class));// 关闭应用上下文applicationContext.close();}/*** 带名 注册到 ioc 容器* @param register* @param beanName*/public static void registerUserBeanDefinition(BeanDefinitionRegistry register, String beanName) {BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);beanDefinitionBuilder.addPropertyValue("id", 1).addPropertyValue("name", "xiaoge");// 构建 BeanDefinitionAbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();// 判断如果beanName存在时if (StringUtils.isEmpty(beanName)) {// 注册 BeanDefinition 非命名方式(不带名称) 注册BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, register);} else {// 注册 BeanDefinition 命名方式(带名称) 注册register.registerBeanDefinition(beanName, beanDefinition);}}public static void registerUserBeanDefinition(BeanDefinitionRegistry register) {registerUserBeanDefinition(register,null);}// 定义当前类做为 Spring Bean (组件)@Component // 2. 通过 @Component 方式定义public static class Config {/*** 通过 Java 注解的方式, 定义了一个 Bean* @return*/@Bean(name = {"user", "user-xiaoge"}) // 1. 通过 @Bean 方式定义public User user() {User user = new User();user.setId(1L);user.setName("xiaoge");return user;}}}/*运行结果:Config 类型的所有 Beans: {annotationBeanDefinitionDemo.Config=org.xiaoge.thinking.in.spring.bean.definition.AnnotationBeanDefinitionDemo$Config@fa4c865}User 类型的所有 Beans: {xiaoge-niubi=User{id=1, name='xiaoge'}, org.xiaoge.thinking.in.spring.ioc.overview.domain.User#0=User{id=1, name='xiaoge'}, user=User{id=1, name='xiaoge'}}*/
Bean实例化(Instantiation)
bean-instantiation-context.xml
special-bean-instantiation-context.xml
org.xiaoge.thinking.in.spring.bean.factory.UserFactory
org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory
org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory
org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory
User.java
package org.xiaoge.thinking.in.spring.ioc.overview.domain;/*** @Classname User* @Date 2022/10/17 14:57* @Created by ZhangXiao* @Description TODO*/
public class User {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}public static User createUser() {User user = new User();user.setId(1L);user.setName("xiaoge");return user;}
}
UserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** {@link User} 工厂类** @Classname DefaultUserFactory* @Date 2022/11/8 17:19* @Created by ZhangXiao* @Description*/
public interface UserFactory {default User createUser() {return User.createUser();}}
DefaultUserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;/*** @Classname DefaultUserFactory* @Date 2022/11/8 17:23* @Created by ZhangXiao* @Description TODO*/
public class DefaultUserFactory implements UserFactory {
}
UserFactoryBean.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.springframework.beans.factory.FactoryBean;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** {@link User} Bean 的 {@link FactoryBean} 实现** 用FactoryBean 相当于 又 实例化 又 初始化** @Classname UserFactoryBean* @Date 2022/11/8 17:32* @Created by ZhangXiao* @Description TODO*/
public class UserFactoryBean implements FactoryBean {@Overridepublic Object getObject() throws Exception {return User.createUser();}@Overridepublic Class> getObjectType() {return User.class;}}
BeanInstantiationDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** @Classname BeanInstantiationDemo* @Date 2022/11/8 17:15* @Created by ZhangXiao* @Description Bean 实例化 示例** 实例化:是对象创建的过程。比如使用构造方法new对象,为对象在内存中分配空间。* 初始化:是为对象中的属性赋值的过程。** 1. 通过构造器方法这里就不写了, 之前写过* 2. 通过静态工厂方法* 3. 通过Bean工厂方法* 4. 通过FactoryBean**/
public class BeanInstantiationDemo {public static void main(String[] args) {// 配置xml配置文件// 启动spring应用上下文BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-instantiation-context.xml");// 1. 通过静态工厂方法User user = beanFactory.getBean("user-by-static-method", User.class);// 2. 通过Bean工厂方法User userByInstanceMethod = beanFactory.getBean("user-by-instance-method", User.class);// 3. 通过FactoryBeanUser userByFactoryBean = beanFactory.getBean("user-by-factory-bean", User.class);System.out.println(user);System.out.println(userByInstanceMethod);System.out.println(userByFactoryBean);System.out.println(user == userByInstanceMethod);System.out.println(user == userByFactoryBean);}}// 运行结果
User{id=1, name='xiaoge'}
User{id=1, name='xiaoge'}
User{id=1, name='xiaoge'}
false
false
SpecialBeanInstantiationDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;import java.util.Iterator;
import java.util.ServiceLoader;/*** 特殊的 Bean 实例化 示例* 1. ServiceLoaderFactoryBean* 2. AutowireCapableBeanFactory* 3. BeanDefinitionRegistry这里就不写了, 之前写过** 实例化:是对象创建的过程。比如使用构造方法new对象,为对象在内存中分配空间。* 初始化:是为对象中的属性赋值的过程。** @Classname SpecialBeanInstantiaionDemo* @Date 2022/11/8 17:42* @Created by ZhangXiao* @Description TODO*/
public class SpecialBeanInstantiationDemo {public static void main(String[] args) {// 配置xml配置文件// 启动spring应用上下文ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/special-bean-instantiation-context.xml");// 通过 ApplicationContext 获取 AutowireCapableBeanFactoryAutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();ServiceLoader userFactoryServiceLoader = beanFactory.getBean("userFactoryServiceLoader", ServiceLoader.class);displayServiceLoad(userFactoryServiceLoader);demoServiceLoader();// 创建 UserFactory 对象, 通过 AutowireCapableBeanFactoryUserFactory userFactory = beanFactory.createBean(DefaultUserFactory.class);System.out.println(userFactory.createUser());}/*** 这种方式可以实例化多个bean, 默认去找META-INF/services* 而我们写的是三个同样的Bean * org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory* org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory* org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory* 所以这里只会创建一个**/private static void demoServiceLoader() {ServiceLoader serviceLoader = ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());displayServiceLoad(serviceLoader);}/*** 这种方式只会找一个, 找我们关注的设置了serviceType的* @param serviceLoader*/private static void displayServiceLoad(ServiceLoader serviceLoader) {Iterator iterator = serviceLoader.iterator();while(iterator.hasNext()) {UserFactory userFactory = iterator.next();System.out.println(userFactory.createUser());}}}// 运行结果
User{id=1, name='xiaoge'}
User{id=1, name='xiaoge'}
User{id=1, name='xiaoge'}
Bean初始化(Initialization)
User.java
package org.xiaoge.thinking.in.spring.ioc.overview.domain;/*** @Classname User* @Date 2022/10/17 14:57* @Created by ZhangXiao* @Description TODO*/
public class User {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}public static User createUser() {User user = new User();user.setId(1L);user.setName("xiaoge");return user;}
}
UserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** {@link User} 工厂类** @Classname DefaultUserFactory* @Date 2022/11/8 17:19* @Created by ZhangXiao* @Description*/
public interface UserFactory {default User createUser() {return User.createUser();}}
DefaultUserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.springframework.beans.factory.InitializingBean;import javax.annotation.PostConstruct;/*** @Classname DefaultUserFactory* @Date 2022/11/8 17:23* @Created by ZhangXiao* @Description TODO*/
public class DefaultUserFactory implements UserFactory, InitializingBean {// 基于 @PostConstruct 注解@PostConstructpublic void init() {System.out.println("@PostConstruct : UserFactory 初始化中.....");}public void initUserFactory() {System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中.....");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中.....");}
}
BeanInitializationDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;/*** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.bean.definition* @Classname BeanInitializationDemo* @Date 2022/11/21 10:26* @Author zhangxiao* @Description Bean 初始化 示例** 实例化:是对象创建的过程。比如使用构造方法new对象,为对象在内存中分配空间。* 初始化:是为对象中的属性赋值的过程。** 1. @PostConstruct 标注方法* 2. InitializingBean 接口* 3. 自定义方法* 1. xml 这里就不说了* 2. @Bean 初始化 方法* 3. AbstractBeanDefinition#setlnitMethodName(String) 初始化方法*/
@Configuration
public class BeanInitializationDemo {public static void main(String[] args) {// 1. 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 2. 注册 Configuration Class 配置类applicationContext.register(BeanInitializationDemo.class);// 3. 开启 spring 应用上下文applicationContext.refresh();// 4. 依赖查找applicationContext.getBean(UserFactory.class);// 5. 关闭 spring 应用上下文applicationContext.close();}@Bean(initMethod = "initUserFactory")public UserFactory userFactory(){return new DefaultUserFactory();}}// 运行结果
@PostConstruct : UserFactory 初始化中.....
InitializingBean#afterPropertiesSet : UserFactory 初始化中.....
自定义初始化方法 initUserFactory() : UserFactory 初始化中.....
Bean 延迟初始化 (Lazy Initialization)
问题: 当某个Bean定义为延迟初始化,那么,Spring容器返回的对象与非延迟的对象存在怎样的差异?
User.class
package org.xiaoge.thinking.in.spring.ioc.overview.domain;/*** @Classname User* @Date 2022/10/17 14:57* @Created by ZhangXiao* @Description TODO*/
public class User {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}public static User createUser() {User user = new User();user.setId(1L);user.setName("xiaoge");return user;}
}
UserFactory.class
package org.xiaoge.thinking.in.spring.bean.factory;import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** {@link User} 工厂类** @Classname DefaultUserFactory* @Date 2022/11/8 17:19* @Created by ZhangXiao* @Description*/
public interface UserFactory {default User createUser() {return User.createUser();}}
DefaultUserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.springframework.beans.factory.InitializingBean;import javax.annotation.PostConstruct;/*** @Classname DefaultUserFactory* @Date 2022/11/8 17:23* @Created by ZhangXiao* @Description TODO*/
public class DefaultUserFactory implements UserFactory, InitializingBean {// 基于 @PostConstruct 注解@PostConstructpublic void init() {System.out.println("@PostConstruct : UserFactory 初始化中.....");}public void initUserFactory() {System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中.....");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中.....");}
}
BeanInitializationDemo
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;/*** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.bean.definition* @Classname BeanInitializationDemo* @Date 2022/11/21 10:26* @Author zhangxiao* @Description Bean 初始化 示例** 实例化:是对象创建的过程。比如使用构造方法new对象,为对象在内存中分配空间。* 初始化:是为对象中的属性赋值的过程。** 1. Lazy 延迟加载* 2. 非延迟加载*/
@Configuration
public class BeanInitializationDemo {public static void main(String[] args) {// 1. 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 2. 注册 Configuration Class 配置类applicationContext.register(BeanInitializationDemo.class);// 3. 开启 spring 应用上下文applicationContext.refresh();// 4. 非延迟初始化在 Spring 应用上下文启动完成后, 被初始化System.out.println("Spring 应用上下文已启动...");// 4. 依赖查找UserFactory userFactory = applicationContext.getBean(UserFactory.class);System.out.println(userFactory);// 5. 关闭 spring 应用上下文applicationContext.close();}@Bean(initMethod = "initUserFactory")@Lazy // 延迟加载//@Lazy(value = false) // 非延迟加载public UserFactory userFactory(){return new DefaultUserFactory();}}// 延迟加载
Spring 应用上下文已启动...
@PostConstruct : UserFactory 初始化中.....
InitializingBean#afterPropertiesSet : UserFactory 初始化中.....
自定义初始化方法 initUserFactory() : UserFactory 初始化中.....
org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory@38364841// 非延迟加载
@PostConstruct : UserFactory 初始化中.....
InitializingBean#afterPropertiesSet : UserFactory 初始化中.....
自定义初始化方法 initUserFactory() : UserFactory 初始化中.....
Spring 应用上下文已启动...
org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory@49070868
实例化或者说初始化所有剩余非延迟加载的Bean
Bean销毁(Destroy)
问题: 假设以上三种方式均在同一 Bean 中定义, 那么这些方法的执行顺序是怎样?
User.java
package org.xiaoge.thinking.in.spring.ioc.overview.domain;/*** @Classname User* @Date 2022/10/17 14:57* @Created by ZhangXiao* @Description TODO*/
public class User {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}public static User createUser() {User user = new User();user.setId(1L);user.setName("xiaoge");return user;}
}
UserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** {@link User} 工厂类** @Classname DefaultUserFactory* @Date 2022/11/8 17:19* @Created by ZhangXiao* @Description*/
public interface UserFactory {default User createUser() {return User.createUser();}}
DefaultUserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;/*** @Classname DefaultUserFactory* @Date 2022/11/8 17:23* @Created by ZhangXiao* @Description TODO*/
public class DefaultUserFactory implements UserFactory, InitializingBean, DisposableBean {// 基于 @PostConstruct 注解@PostConstructpublic void init() {System.out.println("@PostConstruct : UserFactory 初始化中.....");}public void initUserFactory() {System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中.....");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中.....");}// 基于 @PreDestroy 注解@PreDestroypublic void preDestroy() {System.out.println("@PreDestroy : UserFactory 销毁中.....");}public void doDestroy() {System.out.println("自定义销毁方法 doDestroy() : UserFactory 销毁中.....");}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean#destroy() : UserFactory 销毁中.....");}
}
BeanInitializationDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;/*** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.bean.definition* @Classname BeanInitializationDemo* @Date 2022/11/21 10:26* @Author zhangxiao* @Description Bean 初始化 示例** 实例化:是对象创建的过程。比如使用构造方法new对象,为对象在内存中分配空间。* 初始化:是为对象中的属性赋值的过程。** 1. @PreDestroy标注方法* 2. 实现DisposableBean接口的destroy()方法* 3. 自定义方法*/
@Configuration
public class BeanInitializationDemo {public static void main(String[] args) {// 1. 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 2. 注册 Configuration Class 配置类applicationContext.register(BeanInitializationDemo.class);// 3. 开启 spring 应用上下文applicationContext.refresh();// 4. 非延迟初始化在 Spring 应用上下文启动完成后, 被初始化System.out.println("Spring 应用上下文已启动...");// 5. 依赖查找UserFactory userFactory = applicationContext.getBean(UserFactory.class);System.out.println(userFactory);System.out.println("Spring 应用上下文准备关闭...");// 6. 关闭 spring 应用上下文applicationContext.close();System.out.println("Spring 应用上下文已关闭...");}@Bean(initMethod = "initUserFactory", destroyMethod = "doDestroy")@Lazy(value = false)public UserFactory userFactory(){return new DefaultUserFactory();}}// 运行结果
@PostConstruct : UserFactory 初始化中.....
InitializingBean#afterPropertiesSet() : UserFactory 初始化中.....
自定义初始化方法 initUserFactory() : UserFactory 初始化中.....
Spring 应用上下文已启动...
org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory@38364841
Spring 应用上下文准备关闭...
@PreDestroy : UserFactory 销毁中.....
DisposableBean#destroy() : UserFactory 销毁中.....
自定义销毁方法 doDestroy() : UserFactory 销毁中.....
Spring 应用上下文已关闭...
销毁所有的BeanFactory
这里会做一个统计, 统计有多少个Bean实现了destroy方法, 它会足一的去进行销毁
这里会强制转换成DisposableBean
然后去掉它的destroy方法
因为这个方法被DisposableBean接口声明了
@PreDestroy实现方式
剩下的跟上面一样, @PostConstruct也是这么初始化的
Bean垃圾回收(GC)
关闭Spring容器〈应用上下文)
执行GC
Spring Bean覆盖的finalize()方法被回调
完成以上三步
DefaultUserFactory.java
package org.xiaoge.thinking.in.spring.bean.factory;import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;/*** @Classname DefaultUserFactory* @Date 2022/11/8 17:23* @Created by ZhangXiao* @Description TODO*/
public class DefaultUserFactory implements UserFactory, InitializingBean, DisposableBean {// 基于 @PostConstruct 注解@PostConstructpublic void init() {System.out.println("@PostConstruct : UserFactory 初始化中.....");}public void initUserFactory() {System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中.....");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中.....");}// 基于 @PreDestroy 注解@PreDestroypublic void preDestroy() {System.out.println("@PreDestroy : UserFactory 销毁中.....");}public void doDestroy() {System.out.println("自定义销毁方法 doDestroy() : UserFactory 销毁中.....");}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean#destroy() : UserFactory 销毁中.....");}@Overridepublic void finalize() throws Throwable {System.out.println("当前 DefaultUserFactory 对象正在被垃圾回收.....");}
}
BeanGarbageCollectionDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;
import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.bean.definition* @Classname BeanGarbageCollectionDemo* @Date 2022/11/21 16:46* @Author zhangxiao* @Description TODO*/
public class BeanGarbageCollectionDemo {public static void main(String[] args) throws InterruptedException {// 1. 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 2. 注册 Configuration Class 配置类applicationContext.register(BeanInitializationDemo.class);// 3. 开启 spring 应用上下文applicationContext.refresh();// 4. 关闭 spring 应用上下文applicationContext.close();System.out.println("Spring 应用上下文已关闭...");Thread.sleep(5000);// 强制执行GC finalize方法不一定完全被回调, 这个不是必须的, 只是模拟, spring容器中的Bean怎么被回收的System.gc();Thread.sleep(5000);}}// 运行结果
@PostConstruct : UserFactory 初始化中.....
InitializingBean#afterPropertiesSet() : UserFactory 初始化中.....
自定义初始化方法 initUserFactory() : UserFactory 初始化中.....
@PreDestroy : UserFactory 销毁中.....
DisposableBean#destroy() : UserFactory 销毁中.....
自定义销毁方法 doDestroy() : UserFactory 销毁中.....
Spring 应用上下文已关闭...
当前 DefaultUserFactory 对象正在被垃圾回收.....
如何注册一个 Spring Bean?
答: 通过BeanDefinition和外部单体对象来注册
BeanDefinition这里不做例子上面有, 外部单体对象注册如下:
SingletonBeanRegistrationDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;/*** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.bean.definition* @Classname SingletonBeanRegistrationDemo* @Date 2022/11/21 17:39* @Author zhangxiao* @Description TODO*/
public class SingletonBeanRegistrationDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 创建一个外部 UserFactory 对象UserFactory userFactory = new DefaultUserFactory();ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();// 注册外部单例 beanbeanFactory.registerSingleton("userFactory", userFactory);// 开启 spring 应用上下文applicationContext.refresh();// 通过依赖查找的方式来获取 UserFactoryUserFactory userFactoryByLookup = beanFactory.getBean("userFactory", UserFactory.class);System.out.println("userFactory == userFactoryByLookup : " + (userFactory == userFactoryByLookup));// 关闭 spring 应用上下文applicationContext.close();}}// 运行结果
userFactory == userFactoryByLookup : true
SingletonBeanRegistrationDemo.java
package org.xiaoge.thinking.in.spring.bean.definition;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.xiaoge.thinking.in.spring.bean.factory.DefaultUserFactory;
import org.xiaoge.thinking.in.spring.bean.factory.UserFactory;/*** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.bean.definition* @Classname SingletonBeanRegistrationDemo* @Date 2022/11/21 17:39* @Author zhangxiao* @Description TODO*/
public class SingletonBeanRegistrationDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 创建一个外部 UserFactory 对象UserFactory userFactory = new DefaultUserFactory();SingletonBeanRegistry singletonBeanRegistry = applicationContext.getBeanFactory();// 注册外部单例 beansingletonBeanRegistry.registerSingleton("userFactory", userFactory);// 开启 spring 应用上下文applicationContext.refresh();// 通过依赖查找的方式来获取 UserFactoryUserFactory userFactoryByLookup = applicationContext.getBean("userFactory", UserFactory.class);System.out.println("userFactory == userFactoryByLookup : " + (userFactory == userFactoryByLookup));// 关闭 spring 应用上下文applicationContext.close();}}// 运行结果
userFactory == userFactoryByLookup : true
为什么可以用applicationContext取到? 因为它是委派来实现的它是通过获取BeanFactory来获取bean
什么是 Spring BeanDefinition?
BeanDefinition它实际上是一个关于Bean的定义的元信息, 这个接口可以允许我们存储, 就允许我们getter/setter的方式来来进行这个操作, 我们之前在xml中配置的那些东西, 其实就是是在实现接口中的方法, 例如:
等这里就不一一列举了
Spring容器是怎样管理注册 Bean