spring,getBean的源码分析

7 篇文章 0 订阅
3 篇文章 0 订阅

准备材料

pom.xml只有两个依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="schoolService" class="org.dgm.springbasicdemo.SchoolService">
    <property name="schoolname" value="第二百五中学"/>
</bean>

<bean id="userService" class="org.dgm.springbasicdemo.UserServiceImpl">
    <property name="school" ref="schoolService"></property>
</bean>


</beans>

两个用作spring 的bean

public class SchoolService {

private String schoolname;

@Override
public String toString() {
    return "这是:"+schoolname;
}

public String getSchoolname() {
    return schoolname;
}

public void setSchoolname(String schoolname) {
    this.schoolname = schoolname;
}
}

UserServiceImpl

public class UserServiceImpl {

private SchoolService schoolService;
@Override
public String toString() {
return "user对象,我在 "+schoolService.toString();
}
}

main方法:

public static void main(String args[]){
    // resource
    ClassPathResource classPathResource = new ClassPathResource("beans.xml");
    //factory
    BeanDefinitionRegistry factory = new DefaultListableBeanFactory();

    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(classPathResource);

    //拿到factory后处理数据
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) factory;
    //取bean
        SchoolService schoolService = (SchoolService) defaultListableBeanFactory.getBean("schoolService");
    //取bean
        SchoolService schoolService2 = (SchoolService) defaultListableBeanFactory.getBean("schoolService");
    //打印
    System.out.printf(schoolService.toString());

}

spring 管理所有的对象,那它是怎么生成对象的呢?

spring 配置上使用 了lazy 方式,其对象会在getBean的时候生成,我们以此来跟踪相应的内容.

xml的bean里配置了类路径 ,很容易能联想到,其是用反射的方式来new一个对象,返回给使用者的..我们跟踪代码,以下为生成bean的相关线程栈情况

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
      at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
      at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      - locked <0x4f7> (a java.util.concurrent.ConcurrentHashMap)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.dgm.springbasicdemo.App.main(App.java:22)

具体代码:
这里写图片描述
由上可知,内容是使用这个java.lang.reflect.Constructor 来反射生成对象的

第二次取这个bean,会发生什么?

如果是单例,

bean的内容内容存在DefaultSingletonBeanRegistry对象 Map

如果是多例

设置一下bean的scope,

<bean id="schoolService" class="org.dgm.springbasicdemo.SchoolService" scope="prototype">
    <property name="schoolname" value="第二百五中学"/>
</bean>

第二次取和第一次是一样的,都是重新新建一个bean

同时,我们也可以看到 AbstractBeanFactory类的下面这个注册方法.注释中的这一行 “Only applies to singletons.”

/**
* Add the given bean to the list of disposable beans in this factory,
* registering its DisposableBean interface and/or the given destroy method
* to be called on factory shutdown (if applicable). Only applies to singletons.
* @param beanName the name of the bean
* @param bean the bean instance
* @param mbd the bean definition for the bean
* @see RootBeanDefinition#isSingleton
* @see RootBeanDefinition#getDependsOn
* @see #registerDisposableBean
* @see #registerDependentBean
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {

是怎么注入properties的?

入口: AbstractAutowireCapableBeanFactory.populateBean

跟踪代码后发现,注入properties明显也是 通过反射拿到 set方法后执行,(所以,如果没有set方法,是会抛错的!)
这里写图片描述
从factory 里面的逻辑 执行 BeanWrapperImpl中的方法.

在操作这些对象的时候,不是直接把 bean 对象传来传去,而是用 BeanWrapperImpl来包裹.

关于注入依赖的bean怎么个逻辑?

这个和上面的 properties是一样的逻辑,都是使用set方法来处理。参考线程如下:

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
      at org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler.setValue(BeanWrapperImpl.java:325)
      at org.springframework.beans.AbstractNestablePropertyAccessor.processLocalProperty(AbstractNestablePropertyAccessor.java:467)
      at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:290)
      at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:278)
      at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95)
      at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1564)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
      at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1531)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1276)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      - locked <0x505> (a java.util.concurrent.ConcurrentHashMap)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.dgm.springbasicdemo.App.main(App.java:26)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值