spring源码阅读-推断构造方法

如何构造一个对象?

1、默认情况下,或者只有一个构造方法的情况下,就会使用默认构造方法或者唯一的一个构造方法

2、由程序员指定构造方法入参值,通过getBean()的方式获取,可以指定参数类型以及个数,但是该bean需要为LazyBean或者原型bean,否则在spring启动的时候就已经创建好存入单例池中,getBean()也只会取到单例池种的bean。

		UserService userService = applicationContext.getBean("userService", UserService.class);

3、由程序员自己注册Bean然后指定参数个数以及类型

public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext =
				new AnnotationConfigApplicationContext(BeanNameAutoProxyCreatorDemo.class);

		AbstractBeanDefinition rawBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
		rawBeanDefinition.setBeanClass(UserService.class);
		rawBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new User());
		applicationContext.registerBeanDefinition("userService",rawBeanDefinition);
		applicationContext.refresh();
		UserService userService = (UserService)applicationContext.getBean("userService");

4、由程序员自己指定第N+1个参数的类型或bean名字

类型

public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext =
				new AnnotationConfigApplicationContext(BeanNameAutoProxyCreatorDemo.class);

		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
		rawBeanDefinition.setBeanClass(UserService.class);
        //指定第二个参数的类型是User
		beanDefinition .getConstructorArgumentValues().addIndexedArgumentValue(1,new User());

		applicationContext.registerBeanDefinition("userService",beanDefinition );
		applicationContext.refresh();
		UserService userService = (UserService)applicationContext.getBean("userService");

名字

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
		beanDefinition.setBeanClass(UserService.class);
		beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1,new RuntimeBeanNameReference("orderService"));

5、通过指定spring自己选择构造方法

<bean id="userService" class="com.tuling.UserService" autowire="constructor"></bean>

6、通过程序员添加@autowire注解选择指定的构造方法

@Autowired
	public UserService(User user) {
		this.user = user;
	}

7、(这一点功能比较鸡肋,但是在推断构造方法中有用到,就顺带提一下)注册bean的时候可以直接指定返回的实例对象

AbstractBeanDefinition rawBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
		rawBeanDefinition.setBeanClass(UserService.class);
		rawBeanDefinition.setInstanceSupplier(new Supplier<Object>() {
			@Override
			public Object get() {
				return new User();
			}
		});
		applicationContext.registerBeanDefinition("userService",rawBeanDefinition);
		applicationContext.refresh();
		User userService = (User)applicationContext.getBean("userService");

8.

核心代码

createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 加载beanName所对应的类
		Class<?> beanClass = resolveBeanClass(mbd, beanName);
		//这个bean不是公共类或者没有开启访问私有成员的权限,则抛出异常
		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());
		}

		// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// @Bean对应的BeanDefinition
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 一个原型BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来,避免每次都进行构造方法推断
		boolean resolved = false;
		boolean autowireNecessary = false;
		//当getBean的方式没有传入参数,则尝试走缓存
		if (args == null) {
			//doublecheck加锁
			synchronized (mbd.constructorArgumentLock) {
				//resolvedConstructorOrFactoryMethod代表缓存的构造方法
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					// autowireNecessary表示有没有必要要进行注入,比如当前BeanDefinition用的是无参构造方法
					// 那么autowireNecessary为false,否则为true,表示需要给构造方法参数注入值
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			// 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
			if (autowireNecessary) {
				// 方法内会拿到缓存好的构造方法的入参
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 构造方法已经找到了,但是没有参数,那就表示是无参,直接进行实例化
				return instantiateBean(beanName, mbd);
			}
		}
		/**推断构造方法*/
		// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
		// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
		//下面有详细代码
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

		// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
		// 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
		// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
		// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
		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.getPreferredConstructor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值