SpringIOC-Bean配置及源码

 

创建bean:

1.默认构造函数

    spring.xml  <bean class="com.test.spring.HelloSpring"></bean>

    HelloSpring.java   HelloSpring() {}

2.指定构造函数

    <bean class="com.test.spring.HelloSpring">

            <constructor-arg index="0" value="zhangsan"></constructor-arg>

            <constructor-arg name="age" value="1"></constructor-arg>

        </bean>

        public HelloSpring(String name, int age) {}

3.静态工厂方法 factory-method="build"。场景:A/B测试

    spring.xml

    <bean class="com.test.spring.HelloSpring" factory-method="build">

            <constructor-arg name="type" value="A"></constructor-arg>

        </bean>

        HelloSpring.java

        public static HelloSpring build(String type) {

            if("A".equals(type)) {

                return new HelloSpring("张三",1);

            }else if("B".equals(type)){

                return new HelloSpring("李四",2);

            }else {

                throw new IllegalArgumentException("type must be A OR B");

            }

        }

4.FactoryBean创建。创建的可能并不是类本身的对象,场景:SqlSessionFactory

    <bean id="driver" class="com.test.spring.FactoryBeanSpring">

            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306"></property>

        </bean>

        class FactoryBeanSpring implements FactoryBean{

        private String jdbcUrl;

        public Object getObject() throws Exception {

        return DriverManager.getDriver(jdbcUrl);

        }

        public Class getObjectType() {

        return java.sql.Driver.class;

        }

        public boolean isSingleton() {

        return true;

        }

        }

依赖注入:

    HelloSpring的成员变量:WorldSpring

1.set方法注入

    <bean class="com.test.spring.HelloSpring" >

            <property name="worldSpring" ref="world" />

        </bean>

        <bean id="world" class="com.test.spring.WorldSpring" ></bean>

2.构造方法注入

    <bean class="com.test.spring.HelloSpring" >

            <constructor-arg name="worldSpring">

                <bean class="com.test.spring.WorldSpring" />

            </constructor-arg>

        </bean>

3.自动注入:byNamebyType。默认是byName

    <bean class="com.test.spring.HelloSpring" autowire="byName" />

        <bean id="worldSpring" class="com.test.spring.WorldSpring" />

4.方法注入: lookup-method。场景:一个单例bean依赖一个多例bean.该操作基于动态代理技术。也可以通过实现BeanFactoryAware接口来获取BeanFactory实例,从而直接调用getBean()方法获取新实例.

        <bean class="com.test.spring.LookupMethodSpring" >

            <lookup-method name="getHello" ></lookup-method>

        </bean>

        public abstract class LookupMethodSpring {

        public abstract HelloSpring getHello();

        public void sayHello() {

        getHello().sayHello();

        }

        }

 

基本特性:

1.作用范围

scope=prototype多例

scope=singleton 单例。单例对象会缓存于IOC容器,在DefaultSingletonBeanRegistry对象中。

2.生命周期

    创建

    初始化 init-method

    销毁 destory-method  applicationContext关闭时会进行销毁

    3.加载机制

        设置lazy-init,默认为false

            true 懒加载,延迟加载。容器启动会很快

            false 非懒加载,创建即加载。容器启动时能更快的发现错误。

 

创建、读取bean

    1.关键类

        BeanDefinitionbean定义类。bean信息都保存在该类对象中,与xml bean一对一关系

            继承 AttributeAccessorBeanMetadataElementAttributeAccessor.getAttribute()BeanMetadataElement.getSource()

        BeanDefinitionRegistryBean注册器类,id注册,name是设置别名。

            id作为当前bean的存储key注册到BeanDefinitionRegistry注册器中

            name作为别名key注册到AliasRegistry注册器

        BeanDefinitionReaderBean定义读取类。

            BeanDefinitionReader读取xmlload BeanDefinition装载bean定义,注册到BeanDefinitionRegistry

        BeanFactorybean工厂,创建bean

            getBean(String)

              基于IDname 获取一个Bean

            <T> T getBean(Class<T> requiredType) 

             基于Bean的类别获取一个Bean(如果出现多个该类的实例,将会报错。但可以指定 primary=true” 调整优先级来解决该错误 )

            Object getBean(String name, Object... args)

             基于名称获取一个Bean,并覆盖默认的构造参数

            boolean isTypeMatch(String name, Class<?> typeToMatch)

             指定Bean与指定Class 是否匹配

 

BeanFactory

 

BeanFactory是最顶层的一个接口类,它定义了IOC容器的基本功能规范。

 

子类ListableBeanFactory:表示这些 Bean 是可列表的,定义了 Bean 的集合;

 

子类HierarchicalBeanFactory:表示的是这些 Bean 是有继承关系,定义了Bean 之间的关系;

 

子类AutowireCapableBeanFactory:定义 Bean 的自动装配规则,定义了Bean 行为。

 

最终的默认实现类是 DefaultListableBeanFactory,实现了以上所有的接口。

 

 

BeanDefinition

 

Bean对象在Spring实现中是以BeanDefinition来描述的

 

 

BeanDefinitionReader

 

Bean 的解析主要就是对 Spring 配置文件的解析

 

 

 

 

    2.模拟BeanDefinitionRegistry装载过程

        //创建一个简单注册器

        BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();

        //创建bean定义读取器

        BeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);

        // 创建资源读取器、获取资源

        DefaultResourceLoader loader = new DefaultResourceLoader();

        Resource resource = loader.getResource("spring.xml");

        // 装载Bean的定义

        reader.loadBeanDefinitions(resource);

        //通过别名获取

        registry.getAliases("h1");

        //通过id获取

        registry.getBeanDefinition("h1");

        System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));

    3.模拟

 

 

 

 

 

 

 

 

        代码:

 

//注册中心

DefaultListableBeanFactory registry = new DefaultListableBeanFactory();

//读取器

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);

//读取资源

//装载构建bean的定义

reader.loadBeanDefinitions("spring.xml");

registry.getBean("h1");

System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));


分析:

1.DefaultListableBeanFactory既实现了BeanDefinitionRegistry,又实现了BeanFactory。

2.构造函数处打断点,查看调用过程:从下往上看

	at com.test.spring.HelloSpring.<init>(HelloSpring.java:12)

	  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-1)

	  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)

	  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

	  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)

	  BeanUtils.instantiateClass(BeanUtils.java:200)

	  SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)

	  AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1312)

	  AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214)

	  AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)

	  AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)

	  AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)

	  AbstractBeanFactory$$Lambda$5.1846406218.getObject(Unknown Source:-1)

	  DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

	  - locked <0x58a> (a java.util.concurrent.ConcurrentHashMap)

	  AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)

			//先从单例缓存中获取。DefaultListableBeanFactory实现了BeanDefinitionRegistry,所以这里调用的是DefaultSingletonBeanRegistry的getSingleton(String beanName)方法,从singletonObjects(ConcurrentHashMap)中取

			Object sharedInstance = this.getSingleton(beanName); //DefaultSingletonBeanRegistry.getSingleton(beanName);

				//如果值不为空,进入下面

					bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);//查看是不是FactoryBean创建自定义bean

				//如果为空,进入下面,从parentBeanFactory里去获取,类似于classLoader里的双亲委派?

					 BeanFactory parentBeanFactory = this.getParentBeanFactory();

					 parentBeanFactory.getBean(nameToLookup, args);

					//如果还是为空

						//如果是单例

						if (mbd.isSingleton()){sharedInstance = this.getSingleton(beanName, objectFactory);} //DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory objectFactory)

							//DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory objectFactory)

							//第一步 加锁

							//判断是否为空,双重检测

							this.beforeSingletonCreation(beanName);//检测这个bean是否正在被创建

							singletonFactory.getObject();//这个地方往回调,实际上调用的是AbstractBeanFactory.doGetBean的189行,这里传过来objectFactory。

								//AbstractBeanFactory.doGetBean的189行

								this.createBean(beanName, mbd, args);//AbstractAutowireCapableBeanFactory.doCreateBean();

							this.afterSingletonCreation(beanName);

							this.addSingleton(beanName, singletonObject);

						//如果是多例

						if (mbd.isPrototype()) {

							this.beforePrototypeCreation(beanName); //写锁

							prototypeInstance = this.createBean(beanName, mbd, args);

							this.afterPrototypeCreation(beanName);//去锁

						}

	  AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)

	  at com.test.spring.BeanFactoryTest.main(BeanFactoryTest.java:23)

Tips:

1.ctrl+alt+u查看类和子类(实现类)的结构图

 2.ApplicationContext与BeanFactory的区别

是Spring的两大核心接口,都可以当做Spring的容器

3.createBean方法里,实际调用的是AbstractAutowireCapableBeanFactory.doCreateBean
doCreateBean源码

posted @ 2020-05-06 20:47  hy叶子  阅读(192)  评论(0编辑  收藏  举报