目录

简介

源码分析

resolveBeforeInstantiation创建Bean实例

doCreateBean创建Bean实例

Supplier创建实例

FactoryMethod创建实例

自动装配构造函数创建实例

 无参构造函数创建实例

总结


简介

在Spring框架中创建Bean的流程步骤可归纳为getBean -> doGetBean -> createBean -> doCreateBean,其中createBean的核心逻辑就是创建Bean实例。下面通过源码分析来查看具体有几种方式可以创建Bean实例。

源码分析

createBean源码

/**
 * Central method of this class: creates a bean instance,
 * populates the bean instance, applies post-processors, etc.
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;
	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}
	// Prepare method overrides.
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}
	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}
	try {
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

一般情况下创建Bean实例是通过doCreateBean方法来创建的,但是Spring也会给BeanPostProcessors一个机会来返回代理来替代目标实例,就是通过resolveBeforeInstantiation方法来处理这一逻辑,下面通过代码演示resolveBeforeInstantiation是怎样创建Bean实例的。

resolveBeforeInstantiation创建Bean实例

创建User对象

public class User {

	private String name;

	private String address;

	public User() {
	}

	public User(String name, String address) {
		this.name = name;
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "User{" +
				"name='" + name + '\'' +
				", address='" + address + '\'' +
				'}';
	}
}

创建后置处理器

public class UserInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessBeforeInstantiation方法");
		if (beanClass == User.class){
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(beanClass);
			enhancer.setCallback(new UserMethodInterceptor());
			User user = (User) enhancer.create();
			user.setAddress("深圳");
			user.setName("咩哥");
			System.out.println("创建代理对象:" + user);
			return user;
		}
		return null;
	}

	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessAfterInstantiation方法");
		return false;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessBeforeInitialization方法");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessAfterInitialization方法");
		return bean;
	}

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessProperties方法");
		return pvs;
	}
}

创建cglib的回调类

public class UserMethodInterceptor implements MethodInterceptor {

	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
		System.out.println("目标方法执行之前:" + method);
		Object o1 = methodProxy.invokeSuper(o, objects);
		System.out.println("目标方法执行之后:" + method);
		return o1;
	}
}

创建配置文件

<?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.miege.bean.User"></bean>
    <bean id="myInstantiationAwareBeanPostProcessor" class="org.springframework.resolveBeforeInstantiation.UserInstantiationAwareBeanPostProcessor"></bean>
</beans>

测试类

public class Test {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("resolveBeforeInstantiation.xml");
		User user = (User) ac.getBean("user");
		System.out.println("user:" + user);
	}

}

doCreateBean创建Bean实例

在doCreateBean中调用了一个方法createBeanInstance,这个方法就是创建Bean实例的地方,在这个方法中会通过不同的策略来创建Bean实例。

createBeanInstance源码

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
	}
	// 判断是否包含实例供应器,如果有,则用其回调方法创建Bean实例
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}
	// 判断是否有工厂方法,如果有,则用工厂方法创建Bean实例
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
	// Shortcut when re-creating the same bean...
	// 防止创建相同的Bean
	boolean resolved = false;
	// 自动装配
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
			// 有构造参数或工厂方法
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	if (resolved) {
		// 有构造参数创建Bean实例
		if (autowireNecessary) {
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			// 默认的无构造函数创建Bean实例
			return instantiateBean(beanName, mbd);
		}
	}
	// Candidate constructors for autowiring?
	// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	// Preferred constructors for default construction?
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		// 有构造参数创建Bean实例
		return autowireConstructor(beanName, mbd, ctors, null);
	}
	// No special handling: simply use no-arg constructor.
	// 无参构造函数创建对象
	return instantiateBean(beanName, mbd);
}

在这个方法中首先判断是否包含实例供应器,如果有则会通过其中的回调方法来创建实例,否则往下判断是否有工厂方法,没有工厂方法再选择是使用无参构造函数还是有参构造函数创建实例。

Supplier创建实例

创建实例的回调类

public class UserSupplier {

	public static User createUser(){
		return new User("咩哥", "深圳");
	}
}

创建BFPP,BeanFactoryPostProcessor是对BeanDefinition的增强

public class UserSupplierBfpp implements BeanFactoryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		GenericBeanDefinition user = (GenericBeanDefinition) beanFactory.getBeanDefinition("user");
		user.setBeanClass(User.class);
		user.setInstanceSupplier(UserSupplier::createUser);
	}
}

创建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.miege.bean.User"></bean>
	<bean class="org.springframework.supplier.UserSupplierBfpp"></bean>
</beans>

FactoryMethod创建实例

创建factoryMethod,定义了三个工厂方法,为啥Spring依然能精确找到我们需要的方法呢,因为Spring在选择方法的时候会先筛选出类中所有符合条件的方法(是否是静态的&是否是我们指定的工厂方法),再符合条件的方法中再选择差异化最小的方法

public class UserFactoryMethod {

	public static User getUser(String name, String address) {
		return new User(name, address);
	}

	public static User getUser(String name) {
		User user = new User();
		user.setName(name);
		return user;
	}

	public static User getUser() {
		return new User();
	}
}

创建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="org.springframework.factoryMethod.UserFactoryMethod" factory-method="getUser">
		<constructor-arg value="咩哥" ></constructor-arg>
		<constructor-arg value="深圳" ></constructor-arg>
	</bean>
</beans>

自动装配构造函数创建实例

在实体类中的构造方法加@Autowired即可

public class User {

	private String name;

	private String address;

	public User() {
	}

	@Autowired
	public User(String name, String address) {
		this.name = name;
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "User{" +
				"name='" + name + '\'' +
				", address='" + address + '\'' +
				'}';
	}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="com.miege.bean"></context:component-scan>
	<bean id="user" class="com.miege.bean.User">
		<constructor-arg value="咩哥" ></constructor-arg>
		<constructor-arg value="深圳" ></constructor-arg>
	</bean>
</beans>

 无参构造函数创建实例

修改有参构造方式的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.miege.bean.User">
	</bean>
</beans>

总结

一共列举出五种创建Bean实例的方式,但Spring创建对象的流程还远远不止,Spring创建Bean实例可用以下流程图概况:

springboot 动态bean注册 动态创建bean实例 spring_springboot 动态bean注册