注册Spring Bean
XML配置元信息
Java注解元信息
- @Bean
- @Component及其派生注解
- @Import
Java接口继承
ImportSelector
ImportBeanDefinitionRegistrar
Java API
注册普通Bean
命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)
非命名方式:BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,Be anDefinitionRegistry)
void registerBeanDefinition(BeanDefinitionRegistry registry, AbstractBeanDefinition beanDefinition, String beanName) {
if (StringUtils.hasText(beanName)) {
// 注册BeanDefinition
registry.registerBeanDefinition(beanName, beanDefinition);
} else {
// 注册 非命名Bean
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
// 按照 definitionHolder 注册
// BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
// 通过 AbstractBeanDefinition 以及派生类
AbstractBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(User.class);
MutablePropertyValues propertyValues = new MutablePropertyValues()
.add("id", 1)
.add("name", "wangrui");
// propertyValues.addPropertyValue("id", 1);
beanDefinition.setPropertyValues(propertyValues);
registerBeanDefinition(applicationContext, beanDefinition, "user");
registerBeanDefinition(applicationContext, beanDefinition, null);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
// {user=User(id=1, name=wangrui), com.example.boot244.domain.model.User#0=User(id=1, name=wangrui)}
System.out.println(userMap);
注册配置Bean
AnnotatedBeanDefinitionReader#register(Class...)
与AnnotatedBeanDefinitionReader一次只注册单个Bean相比,还有一个扫描器ClassPathBeanDefinitionScanner。但两者区别在于:
AnnotatedBeanDefinitionReader:可以注册任意类
ClassPathBeanDefinitionScanner:只能扫描特定类
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(applicationContext);
reader.register(User.class);
User bean = applicationContext.getBean(User.class);
System.out.println(bean);
注册单例Bean
SingletonBeanRegistry#registerSingleton
void test() throws Exception {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
User user = new User().setId(1).setName("wangrui");
registerSingleton(applicationContext.getBeanFactory(), "user", user);
user = applicationContext.getBean(User.class);
System.out.println(user);
}
public void registerSingleton(SingletonBeanRegistry beanRegistry, String beanname, Object obj) {
beanRegistry.registerSingleton(beanname, obj);
}
实例化Bean
Bean常规方式
通过构造器(配置元信息:XML、Java注解和Java API)
通过静态方法(配置元信息:XML和Java API)
通过实例方法(配置元信息:XML和Java API)
通过FactoryBean(配置元信息:XML、Java注解和Java API)
public class User {
private Integer id;
private String name;
// 静态方法
public static User createUser() {
return new User().setId(1).setName("createUser");
}
}
public class UserFactory {
// 实例方法
public User createUser() {
return new User().setId(1).setName("factory工厂");
}
}
// 通过FactoryBean
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User().setId(1).setName("userFactoryBean");
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
// 注册工具
void registerBeanDefinition(BeanDefinitionRegistry registry, AbstractBeanDefinition beanDefinition, String beanName) {
if (StringUtils.hasText(beanName)) {
// 注册BeanDefinition
registry.registerBeanDefinition(beanName, beanDefinition);
} else {
// 注册 非命名Bean
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
// 按照 definitionHolder 注册
// BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// UserFactoryBean属于FactoryBean方式
applicationContext.register(UserFactory.class, UserFactoryBean.class);
applicationContext.refresh();
// 通过静态工厂方法
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.setFactoryMethod("createUser")
.getBeanDefinition();
registerBeanDefinition(applicationContext, beanDefinition, null);
// 通过实例工厂方法
AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.setFactoryMethodOnBean("createUser", "userFactory")
.getBeanDefinition();
registerBeanDefinition(applicationContext, beanDefinition1, null);
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
System.out.println(userMap);
特殊方式
通过ServiceLoaderFactoryBean(配置元信息:XML、Java注解和Java API)
public interface DemoFactory { }
public class DefaultDemoFactory implements DemoFactory { }
public class StandDemoFactory implements DemoFactory { }
META-INF/services/com.example.boot.service.DemoFactory
# 这里用来展示去重
com.example.boot244.service.DefaultDemoFactory
com.example.boot244.service.StandDemoFactory
com.example.boot244.service.StandDemoFactory
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(ServiceLoaderFactoryBean.class)
.addPropertyValue("serviceType", DemoFactory.class)
.getBeanDefinition();
registerBeanDefinition(applicationContext, beanDefinition, null);
ServiceLoader serviceLoader = applicationContext.getBean(ServiceLoader.class);
serviceLoader.forEach(System.out::println);
通过AutowireCapableBeanFactory#createBean
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
// 此种方式可以触发 依赖注入,但createBean(Class<T> beanClass)不能触发依赖查找
User user = applicationContext.getBeanFactory().createBean(User.class);
System.out.println(user);
通过BeanDefinitionRegistry#registerBeanDefinition
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(User.class)
.addPropertyValue("id", 1)
.addPropertyValue("name", "wangrui")
.getBeanDefinition();
applicationContext.registerBeanDefinition("user", beanDefinition);
User user = applicationContext.getBean(User.class);
System.out.println(user);
Bean初始化
@PostConstruct
实现InitializingBean接口
自定义初始化方法
XML配置:
Java注解:@Bean(initMethod="")
Java API:AbstractBeanDefinition#setInitMethodName
那以上三种方式均在同一Bean中定义,那么这些方法的执行顺序是怎样的呢?
- @PostConstruct
- 实现InitializingBean接口
- 自定义初始化方法
public class Person implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean#afterPropertiesSet() : 初始化中...");
}
@PostConstruct
public void init() {
System.out.println("@PostConstruct : 初始化中...");
}
public void initFactory() {
System.out.println("自定义初始化方法 initUserFactory() : 初始化中...");
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.setInitMethodName("initFactory")
.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, applicationContext);
Person person = applicationContext.getBean(Person.class);
Bean销毁
@PreDestory
实现DisposableBean接口
自定义销毁方法
XML配置:
Java注解:@Bean(destory="")
Java API:AbstractBeanDefinition#setDestroyMethodName
那以上三种方式均在同一Bean中定义,那么这些方法的执行顺序是怎样的呢?
- @PreDestory
- 实现DisposableBean接口
- 自定义销毁方法
public class Person implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean#destroy() : 销毁中...");
}
@PreDestroy
public void destory() {
System.out.println("@PreDestroy : 销毁中...");
}
public void destoryFactory() {
System.out.println("自定义销毁方法 doDestroy() : 销毁中...");
}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.refresh();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.setDestroyMethodName("destoryFactory")
.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, applicationContext);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
applicationContext.close();