深入研究Spring-IoC:源码分析依赖注入

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

1.前言

对于容器创建的过程已经阐述过一遍了,下面是依赖注入的问题。Spring提供的依赖注入的方法主要由两种:一种是通过getBean的方法;另一种是通过注解@Autowaire。

需要指出的是依赖注入的过程是用户第一次向ioc容器索要Bean的时候开始生产的,也可以通过设置BeanDefinition的lazy-init属性来体现实例化。

2.分析

执行代码:

     HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");

getBean方法实现类是AbstractBeanFactory:

        @Override
        public Object getBean(String name) throws Exception {
            BeanDefinition beanDefinition = beanDefinitionMap.get(name);
            if (beanDefinition == null) {
                throw new IllegalArgumentException("No bean named " + name + " is defined");
            }
            Object bean = beanDefinition.getBean();
            if (bean == null) {
                 //核心代码
                bean = doCreateBean(beanDefinition);
                bean = initializeBean(bean, name);
                beanDefinition.setBean(bean);
            }
            return bean;
        }

在其中关键是doCreateBean(beanDefinition)方法,

        protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
            //实例化beanDefinition
            Object bean = createBeanInstance(beanDefinition);
            beanDefinition.setBean(bean);
            //增加属性
            applyPropertyValues(bean, beanDefinition);
            return bean;
        }
    protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {
            return beanDefinition.getBeanClass().newInstance();
        }

调用applyPropertyValues方法:

    protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(this);
            }
            //属性注入的核心代码
            for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
                Object value = propertyValue.getValue();
                if (value instanceof BeanReference) {
                    BeanReference beanReference = (BeanReference) value;
                    value = getBean(beanReference.getName());
                }

                try {
                    Method declaredMethod = bean.getClass().getDeclaredMethod(
                            "set" + propertyValue.getName().substring(0, 1).toUpperCase()
                                    + propertyValue.getName().substring(1), value.getClass());
                    declaredMethod.setAccessible(true);

                    declaredMethod.invoke(bean, value);
                } catch (NoSuchMethodException e) {
                    Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
                    declaredField.setAccessible(true);
                    declaredField.set(bean, value);
                }
            }
        }

3.总结

依赖注入的过程中,getBean是一个起点,之后调用createBean方法,根据BeanDefinition定义生产Bean和属性注入。

其中实例化bean的过程可以采用CGLIB进行。CGLIB是常用的字节码.class生成器类库,提供了一些列api来提供生成和转换Java字节码的功能。

在IOC容器中,提供了SimpleInstantiationStrategy类生产Bean,它提供了两种方式,一种是BeanUtils,它是JVM的反射机制。另一种就是CGLIB的方式。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 深入研究Spring-IoC:源码分析依赖注入

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏