Spring创建对象的主要方式有
-
通过自定义BeanPostProcessor,生成代理对象InstantiationAwareBeanPostProcessor
-
createBean() -> resolveBeforeInstantiation()
-
-
通过supplier创建对象
-
createBean() -> doCreateBean() -> createBeanInstance() -> obtainFromSupplier()
-
-
通过FactoryMethod创建对象
-
createBean() -> doCreateBean() -> createBeanInstance() -> instantiateUsingFactoryMethod()
-
-
通过反射创建对象
-
createBean() -> doCreateBean() -> createBeanInstance() -> instantiateBean()
-
-
通过FactoryBean创建对象
本文介绍下最后一种,如何通过supplier创建Bean(保姆级教程,建议收藏食用(。・ω・。)ノ)
创建测试所需文件
User.java
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(){
}
public User(String name) {
this.name = name;
}
}
CreateSupplier.java
public class CreateSupplier {
public static User createUser() {
return new User("aqin");
}
}
SupplierBeanFactoryPostProcessor.java
public class SupplierBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("user");
GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) beanDefinition;
genericBeanDefinition.setInstanceSupplier(CreateSupplier::createUser);
genericBeanDefinition.setBeanClass(User.class);
}
}
supplier.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.xsd">
<bean id="user" class="com.aqin.custom.supplier.User"></bean>
<bean id="supplierBeanFactoryPostProcessor" class="com.aqin.custom.supplier.SupplierBeanFactoryPostProcessor"></bean>
</beans>
TestSupplier.java
public class TestSupplier {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("supplier.xml");
User user = applicationContext.getBean(User.class);
System.out.println(user.getName());
}
}
测试效果
Debug
由于是测试创建Bean,我们需要在doCreateBean()上打个断点,启动debug,执行到断点位置,如下图:
进入doCreateBean(),下一步到instanceWrapper = createBeanInstance(beanName, mbd, args);,进入createBeanInstance()方法中
进入createBeanInstance()方法后,下一步到Supplier<?> instanceSupplier = mbd.getInstanceSupplier();这里是判断当前beanDefinition中是否包含实例供应器的
继续下一步,我们会发现instanceSupplier=null,咦?……不应该呀?
不用着急,我们仔细看上图中红框框圈住的内容,有一个是beanName,此时,beanName是"supplierBeanFactoryPostProcessor",并非我们要创建的"user"
所以我们直接点击下图中的Resume Program再次进入之前的断点即可
点击上图中的绿三角,就会再次停在一开始我们打断点的位置,如下图:
此时可以看到,当前处理对象的beanName为"user",继续下一步,直到再次执行到Supplier<?> instanceSupplier = mbd.getInstanceSupplier()
进入getInstanceSupplier(),可以发现instanceWrapper已经不是null叻
再向下执行一步,由于instanceSupplier已经有了值,所以会进入if的逻辑,通过obtainFromSupplier()方法返回已获取到的对象
obtainFromSupplier()从给定“供应商”处,获取Bean实例
然后包装一下,再进行初始化
完成(。・ω・。)ノ