BeanDefinition概念
BeanDefinition是Spring框架中定义Bean的配置元信息接口, 包含:
- Bean类名
- Bean行为配置元素, 如作用域, 自动绑定的模式, 生命周期回调等
- 其他Bean引用, 又可称作合作者(Collaborators)或者依赖(Dependencies)
- 配置设置, 比如Bean属性(Properties)

BeanDefinition构建
- 通过BeanDefinitionBuilder
通过AbstractBeanDefinition以及派生类 ```java public class BeanDefinitionCreationDemo {
public static void main(String[] args) {
// 1. 通过BeanDefinitionBuilder构建BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);// 设置属性beanDefinitionBuilder.addPropertyValue("age", 18);beanDefinitionBuilder.addPropertyValue("name", "erha");// 获取实例, 其中beanDefinition并非终态, 还可以自定义修改BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();// 2. 通过AbstractBeanDefinition构建GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();genericBeanDefinition.setBeanClass(User.class);// 设置属性MutablePropertyValues propertyValues = new MutablePropertyValues();
// propertyValues.addPropertyValue(“age”,18); // propertyValues.addPropertyValue(“name”,”erha”);
propertyValues.add("age", 17).add("name", "sansha");genericBeanDefinition.setPropertyValues(propertyValues);
}
}
<a name="AuFW3"></a>## 命名SpringBean每个Bean拥有一个或多个标识符(identifiers), 这些标识符在Bean所在的容器必须是唯一的.<br />通常, 一个Bean仅有一个标识符, 如果需要额外的, 可用别名来扩充.- 基于xml配置时, 可用id/name属性来规定Bean的标识符. 命名官方推荐驼峰- 如果未指定, 容器为Bean自动生成一个唯一的名称(BeanNameGenerator)**Bean的别名**- 复用现有的BeanDefinition- 更具有场景化的命名方法```xml<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><import resource="classpath:/META-INF/dependency-lookup-context.xml"/><!--建立别名--><alias name="user" alias="zhangsan-user"/></beans>
public class BeanAliasDemo {public static void main(String[] args) {// 配置XML配置文件, 启动Spring应用上下文BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:META-INF/bean-definition-context.xml");User aliaUser = beanFactory.getBean("zhangsan-user", User.class);User user = beanFactory.getBean("user", User.class);System.out.println(user == aliaUser);//true}}
注册SpringBean

@Import(AnnotationBeanDefinitionDemo.Config.class) // 3. 通过 @Import进行导入public class AnnotationBeanDefinitionDemo {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 1. 通过 @Bean方式定义, 注意, 注解尽管多种方式, 但是不会重复注册, API会多次注册applicationContext.register(Config.class);applicationContext.refresh();registerUserBeanDefinition(applicationContext,"erHuUser");registerUserBeanDefinition(applicationContext);Map<String, Config> configMap = applicationContext.getBeansOfType(Config.class);Map<String, User> userMap = applicationContext.getBeansOfType(User.class);System.out.println(configMap);// {annotationBeanDefinitionDemo.Config=top.xinzhang0618.spring.bean.AnnotationBeanDefinitionDemo$Config@2c039ac6}System.out.println(userMap);// {user=User{id=1, name='一旦'}, erHuUser=User{id=2, name='二虎'}, top.xinzhang0618.ioc.overview.domain.User#0=User{id=2, name='二虎'}}applicationContext.close();}@Component //2. 通过 @Component方式public static class Config {// 1. 通过 @Bean方式定义@Bean(name = {"user", "yiDanUser"})public User user() {User user = new User();user.setId(1L);user.setName("一旦");return user;}}/*** 通过API注册Bean*/public static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition(User.class);beanDefinitionBuilder.addPropertyValue("id", 2L).addPropertyValue("name", "二虎");if (StringUtils.hasText(beanName)) {// 命名Bean的注册方式registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());} else {// 非命名Bean的注册方式BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);}}public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {registerUserBeanDefinition(registry, null);}}
实例化SpringBean
- 常规方式
- 通过构造器(配置元信息: XML. Java注解和API)
- 通过静态工厂方法
- 通过Bean工厂方法
- 通过FactoryBean
以下代码通过XML配置的方式演示了三种情况
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!--静态方法实例化Bean--><bean id="user-by-static-method" class="top.xinzhang0618.ioc.overview.domain.User"factory-method="createUser"/><!--实例方法实例化Bean--><bean id="user-by-instance-method" factory-bean="userFactory" factory-method="createUser"/><!--通过FactoryBean实例化Bean--><bean id="user-by-factory-bean" class="top.xinzhang0618.spring.bean.factory.UserFactoryBean"/><bean id="userFactory" class="top.xinzhang0618.spring.bean.factory.DefaultUserFactory"/></beans>
public class User {private Long id;private String name;.../*** 通过静态方法构建user* @return*/public static User createUser() {User user = new User();user.setId(1L);user.setName("lisi");return user;}}------------------public interface UserFactory {default User createUser() {return User.createUser();}}----------------------public class DefaultUserFactory implements UserFactory {}-----------------------public class UserFactoryBean implements FactoryBean {@Overridepublic Object getObject() throws Exception {return User.createUser();}@Overridepublic Class<?> getObjectType() {return User.class;}}
public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-instantiation-context.xml");User user = beanFactory.getBean("user-by-static-method", User.class);User userByInstanceMethod = beanFactory.getBean("user-by-instance-method", User.class);User 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);//falseSystem.out.println(userByInstanceMethod == userByFactoryBean);//false}
- 特殊方式
- 通过ServiceLoaderFactoryBean
- 通过AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
- 通过BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)
初始化SpringBean
执行顺序如下:
- @PostConstruct标注方法
- 实现InitializingBean接口的afterPropertiesSet()方法
- 自定义初始化方法
- XML配置:
- Java注解: @Bean(initMethod=”init”)
- Java API: AbstractBeanDefinition#setInitMethosName(String)
- XML配置:
示例代码如下:
@Configurationpublic class BeanInitializationDemo {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();applicationContext.register(BeanInitializationDemo.class);applicationContext.refresh();// 非延迟初始化 在Spring应用启动上下文完成后, 被初始化System.out.println("Spring应用上下文已启动...");UserFactory userFactory = applicationContext.getBean(UserFactory.class);System.out.println(userFactory);applicationContext.close();}@Bean(initMethod = "initUserFactory", destroyMethod = "doDestroy")// @Lazypublic UserFactory userFactory() {return new DefaultUserFactory();}}
public class DefaultUserFactory implements UserFactory , InitializingBean, DisposableBean {// 1. 基于 @PostConstruct 注解实现@PostConstructpublic void init(){System.out.println("userFactory的@PostConstruct初始化");}public void initUserFactory(){System.out.println("@Bean自定义初始化方法");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean#afterPropertiesSet初始化方法");}@PreDestroypublic void preDestroy(){System.out.println("userFactory的@PreDestroy销毁方法");}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean#destroy销毁方法");}public void doDestroy(){System.out.println("@Bean自定义销毁方法");}}
userFactory的@PostConstruct初始化InitializingBean#afterPropertiesSet初始化方法@Bean自定义初始化方法Spring应用上下文已启动...top.xinzhang0618.spring.bean.factory.DefaultUserFactory@19dc67c2userFactory的@PreDestroy销毁方法DisposableBean#destroy销毁方法@Bean自定义销毁方法
注: spring的启动初始化是单线程的
延迟初始化Bean
常用来解决循环依赖问题
- XML配置:
- java注解: @Lazy(true)
非延迟初始化: 先初始化Bean后再启动Spring上下文
延迟初始化: 先启动Spring上下文, 首次调用方法或者字段时, 才进行初始化
销毁SpringBean
执行顺序如下:
- @PreDestroy标注方法
- 实现DisposableBean接口的destory()方法
- 自定义销毁方法
- XML配置:
- Java注解: @Bean(destroy=”destroy”)
- Java API : AbstractBeanDefiniton#setDestroyMethosName(String)
- XML配置:
回收SpringBean
Bean垃圾回收(GC)
- 关闭Spring容器应用上下文
- 执行GC
- SpringBean覆盖的finalize()方法被回调
