前言:在Spring的IOC容器中提供了丰富多样的创建Bean的方式,先上图。
1.通过FactoryBean直接或者间接得到的Bean对象。(这一部分的知识在Spring学习第八天中的FactoryBean小节进行过解释和图示)
目的:通过FactoryBean的方式可以规避创建Bean时复杂的流程(实例化,bpp-begin,bpp-after.....)
结果:直接:通过context.getBean(“&FactoryBeanName”):通过这种方式可以获取到FactoryBean对象
间接:通过context.getBean("FactoryBeanName"):可以得到FactoryBean通过getObject()方法得到的对象
2.通过在xml中为Bean配置< lookup-metyhod/> <replace-method/>来获取对象
目的:通过这样的方式可以在原型模式下引用一个原型模式的bean
1.如果通过常规的方式(单例的Bean对象通过属性注入一个原型模式的Bean对象,会发现每次得到的原型模式的属性都是同一个,没有得到多例的效果)
2.而添加<lookup-method/><replace-method>标签是通过拦截器的方式每次需要的时候都去创建最新的对象,而不会把原型对象缓存起来。
结果:通过getBean()得到对象的类类型是一致的,在标签中设置的方法的返回值类类型也是一致的。但是是否单例/原型,需要根据配置中规则来决定
3.通过以resolveBeforeInstantiation为入口的方式创建Bean
目的:这种方式通过实现InstantiationAwareBeanPostProcessor接口可以选择在Bean的实例化前/后,初始化前/后,属性设置等进行丰富多样的设置
4.通过Supplier的方式创建Bean
目的:本质上还是创建Bean,在创建Bean的过程中可以进行丰富Bean信息的操作。
实现:创建一个实现BeanFactoryPostProcessor接口的子类,实现postProcessorBeanFactory。关于BFPP的内容
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 获取到BeanName:user 的Bean定义信息 BeanDefinition user = beanFactory.getBeanDefinition("user"); // 知识点: // 1.GenericBeanDefinition是BeanDefinition的子类 // 2.GenericBeanDefinition有一个继承自AbstractBeanDefinition的成员属性【类型为Supplier】 GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) user; // 3.Supplier是一个函数式接口(里面有一个唯一方法Get),我们通过Lambda表达式传入一个创建Bean的方法 genericBeanDefinition.setInstanceSupplier(CreateSupplier::createUser); genericBeanDefinition.setBeanClass(User.class); }
获得结果处:如以下代码段
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { / ..... / // 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } / ..... / }
5.通过静态/实例工厂创建Bean
目的:通过静态/实例工厂创建Bean实例,也是通过我们常用的<bean/>标签中的factory-bean,factory-method属性来实现
粗略的流程介绍:
1.判断是静态工厂还是实例工厂,如果是静态工厂的话标志位置为true
2.获取构造函数参数值数组
3.获取所有的构造方法集合,并按照参数个数降序排序
3.1意义:可以减少不必要的判断,比如说参数个数为3,那么参数个数<=2的构造方法就不需要取执行判断了
4.选择合适的构造方法进行实例化