Spring中创建对象的方式整理
在没有使用Spring时,开发者创建对象一般都是使用new/反射创建对象;Spring出来后简化了开发方式,它提供了一个IoC容器的实现,用于帮助开发者以依赖注入的方式管理对象之间的依赖关系,从而将开发者创建对象的所有权转移到IoC容器上,这使得Spring易于整合第三方模块,因此Spring更是一个分层的框架;
对于Spring创建对象的方式创建整理如下:
方式一:自定义BeanPostProcessor,生成代理对象
如实现InstantiationAwareBeanPostProcessor接口,其中InstantiationAwareBeanPostProcessor是一个BeanPostProcessor,它可用于处理bean实例创建前后的回调;

测试如下:
@Test
public void instantiationAwareBeanPostProcessorTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition1 = new GenericBeanDefinition();
definition1.setBeanClass(DemoInstantiationAwareBPP.class);
context.registerBeanDefinition("demoInstantiationAwareBPP", definition1);
GenericBeanDefinition definition2 = new GenericBeanDefinition();
definition2.setBeanClass(InstantiationDemo.class);
context.registerBeanDefinition("instantiationDemo", definition2);
context.refresh();
InstantiationDemo bean = context.getBean(InstantiationDemo.class);
bean.invoke();
}
public class DemoInstantiationAwareBPP implements InstantiationAwareBeanPostProcessor {
private final static Log LOG = LogFactory.getLog(DemoInstantiationAwareBPP.class);
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
LOG.info("beanName:" + beanName + "执行postProcessBeforeInstantiation方法");
// 使用cglib生成代理对象
if (beanClass == InstantiationDemo.class) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanClass);
enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object");
if (!objFlag) {
LOG.info("执行方法" + method + "前");
Object rtn = methodProxy.invokeSuper(o, objects);
LOG.info("执行方法" + method + "后");
return rtn;
} else {
return methodProxy.invokeSuper(o, objects);
}
});
InstantiationDemo bean = (InstantiationDemo) enhancer.create();
LOG.info("创建代理对象:" + bean);
return bean;
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
LOG.info("beanName:" + beanName + "执行postProcessAfterInstantiation方法");
return false;
}
}
public class InstantiationDemo {
private final static Log LOG = LogFactory.getLog(InstantiationDemo.class);
public void invoke() {
LOG.info(this);
LOG.info("InstantiationDemo invoke");
}
}

注:
MethodProxy#invokeSuper是退出当前interceptor的处理,进入下一个callback处理;
MethodProxy#invoke则会继续回调该方法,如果传递给invoke的obj参数出错容易造成递归调用;
方式二:通过反射创建
AbstractAutowireCapableBeanFactory#doCreateBean为真正创建bean的逻辑,该方法是最复杂的,包含了调用构造函数,给bean的属性赋值,调用bean的初始化操作以及生成代理对象;
该方法会调用AbstractAutowireCapableBeanFactory#createBeanInstance实例化对象,如下图;

AbstractAutowireCapableBeanFactory#createBeanInstance
判断Bean定义信息中的resolvedConstructorOrFactoryMethod是否缓存,因为需要根据参数确认到底使用哪个构造器,该过程比较消耗性能,所以采用缓存机制;

通过bean的后置处理器进行获取合适的构造器对象,有且只有一个有参构造或有且只有一个@Autowired注解构造;

创建对象方式
AbstractAutowireCapableBeanFactory#createBeanInstance根据@Autowried自动注入/调用无参构造器创建,进行相应的处理;
- instantiateBean 调用无参数的构造器进行创建对象;
- autowireConstructor @Autowired自动注入,调用构造器注入;
方式三:通过FactoryBean创建对象
AbstractBeanFactory#getObjectForBeanInstance

如果有实现了FactoryBean接口的实例,则从FactoryBean中获取实例;
@Test
public void mainTest13() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MainConfig10.class);
System.out.println("IOC容器创建完成...");
// 调用FactoryBean#getBean方法,入参为Bean id,得到的对象为FactoryBean#getObjectType的对象
// FactoryBean要获取工厂Bean本身,需要在id前加个&
// org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance
Object factoryBean1 = context.getBean("demoFactoryBean");
Object factoryBean2 = context.getBean("demoFactoryBean");
System.out.println("factoryBean1==factoryBean2 :" + (factoryBean1 == factoryBean2));
System.out.println("bean的类型:" + factoryBean1.getClass());
Object factoryBean3 = context.getBean("&demoFactoryBean");
System.out.println("bean的类型:" + factoryBean3.getClass());
}
@Configuration
public class MainConfig10 {
@Bean
public DemoFactoryBean demoFactoryBean() {
return new DemoFactoryBean();
}
}
public class DemoFactoryBean implements FactoryBean<Person> {
/**
* 是否单例进行控制
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
/**
* 返回对象,把对象放到容器中
* @return
* @throws Exception
*/
@Override
public Person getObject() throws Exception {
return new Person();
}
/**
* 返回对象类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Person.class;
}
}

方式四:通过设置BeanDefinition属性Supplier创建对象
AbstractAutowireCapableBeanFactory#createBeanInstance

获取bean的supplier;
AbstractAutowireCapableBeanFactory#obtainFromSupplier

通过Suupplier#get方法获取实例,此时获取实例不是使用反射;
测试如下:
@Test
public void supplierTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(BeanC.class);
definition.setInstanceSupplier((Supplier<BeanC>) BeanC::new);
context.registerBeanDefinition("beanC", definition);
context.refresh();
Assertions.assertNotNull(context.getBean("beanC"));
}
public class BeanC {
private final static Log LOG = LogFactory.getLog(BeanC.class);
public BeanC() {
LOG.info("BeanC constructor");
}
}
![]()
方式五:通过设置BeanDefinition属性factoryMethod创建对象
AbstractAutowireCapableBeanFactory#createBeanInstance

createBeanInstance是实例化对象的过程,如果beanDefinition设置了factoryMethod,则从设置的factoryMethod实例化,而supplier属性的优先级高于factoryMethod,即beanDefinition同时存在supplier和factoryMethod属性时,优先执行supplier的实例化逻辑;
mbd的factoryMethodName在BeanDefiniton加载时赋值的,如下:
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod

factoryMethod使用方式:往beanDefinition设置factoryMethod所属类的beanName和factoryMethodName的属性;
使用factoryMethod实例化对象的解析逻辑:ConstructorResolver#instantiateUsingFactoryMethod
SimpleInstantiationStrategy最终通过对factoryBean反射调用factoryMethod;


测试如下:
beanDefinition只有factoryMethod属性
public class FactoryDemo {
private final static Log LOG = LogFactory.getLog(FactoryDemo.class);
private int num;
private String msg;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public FactoryDemo() {
LOG.info("FactoryDemo no params constructor");
}
public BeanDemo create() {
BeanDemo beanDemo = new BeanDemo();
LOG.info("invoke create without args,beanDemo:" + beanDemo);
return beanDemo;
}
public BeanDemo create(int num, String msg) {
BeanDemo beanDemo = new BeanDemo();
beanDemo.setMsg(msg);
beanDemo.setNum(num);
LOG.info("invoke create with args,beanDemo:" + "[" + beanDemo + "]" + beanDemo.getMsg() + "," + beanDemo.getNum());
return beanDemo;
}
}
public class BeanDemo {
private final static Log LOG = LogFactory.getLog(BeanDemo.class);
private int num;
private String msg;
public BeanDemo() {
LOG.info("BeanDemo constructor");
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
调用无参的factoryMethod
@Test
public void factoryBeanNameTestWithoutArgs() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(FactoryDemo.class);
GenericBeanDefinition definition = new GenericBeanDefinition();
// 设置factoryBean
definition.setFactoryBeanName("factoryDemo");
definition.setFactoryMethodName("create");
definition.setBeanClass(BeanDemo.class);
context.registerBeanDefinition("beanDemo", definition);
context.refresh();
System.out.println(context.getBean(BeanDemo.class));
}

调用有参factoryMethod
@Test
public void factoryBeanNameWithArgsTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(FactoryDemo.class);
GenericBeanDefinition definition = new GenericBeanDefinition();
// 设置factoryBean
definition.setFactoryBeanName("factoryDemo");
definition.setFactoryMethodName("create");
ConstructorArgumentValues argumentValues = new ConstructorArgumentValues();
argumentValues.addGenericArgumentValue("test", "java.lang.String");
argumentValues.addGenericArgumentValue(1, "int");
definition.setConstructorArgumentValues(argumentValues);
definition.setBeanClass(BeanDemo.class);
context.registerBeanDefinition("beanDemo", definition);
context.refresh();
System.out.println(context.getBean(BeanDemo.class));
}

beanDefinition有factoryMethod属性和supplier属性
@Test
public void supplierOrderTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(FactoryDemo.class);
GenericBeanDefinition definition = new GenericBeanDefinition();
// 设置factoryBean
definition.setFactoryBeanName("factoryDemo");
definition.setFactoryMethodName("create");
definition.setBeanClass(BeanDemo.class);
context.registerBeanDefinition("beanDemo", definition);
definition.setInstanceSupplier((Supplier<BeanDemo>) BeanDemo::new);
context.refresh();
Assertions.assertNotNull(context.getBean("beanDemo"));
}

此时优先执行supplier逻辑;
Spring创建对象方式的整理图

Spring实例化策略整理


浙公网安备 33010602011771号