tiny-spring 学习笔记(一)—— IOC

学习项目 Github 地址:code4craft/tiny-spring

1、step-1-container-register-and-get

使用map当做bean的容器

1.1  HelloWorldService.java

public class HelloWorldService {

    public void helloWorld(){
        System.out.println("Hello World!");
    }
}

1.2  BeanDefinition.java

public class BeanDefinition {

    private Object bean;

    public BeanDefinition(Object bean) {
        this.bean = bean;
    }

    public Object getBean() {
        return bean;
    }

}

简单的bean文件,初始化时为bean复制,通过getBean()获取。

1.3  BeanFactory.java

public class BeanFactory {

	private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

	public Object getBean(String name) {
		return beanDefinitionMap.get(name).getBean();
	}

	public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
		beanDefinitionMap.put(name, beanDefinition);
	}

}

简单的map容器,两个函数分别实现对bean的插入和读取

1.4  BeanFactoryTest.java

public class BeanFactoryTest {

	@Test
	public void test() {
		// 1.初始化beanfactory
		BeanFactory beanFactory = new BeanFactory();

		// 2.注入bean
		BeanDefinition beanDefinition = new BeanDefinition(new HelloWorldService());
		beanFactory.registerBeanDefinition("helloWorldService", beanDefinition);

        // 3.获取bean
        HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
        helloWorldService.helloWorld();


    }
}

大概流程:

1、目标:执行HelloWorldService的helloWorld方法,但不通过new HelloWorldService()来实现

2、这里先new了一个BeanFactory和一个BeanDefinition,在初始化BeanDefinition的时候new 了一个HelloWorldService

3、将BeanDefinition插入到BeanFactory的map属性

4、需要时,直接从BeanFactory中get到这个BeanDefinition,并获取其中的HelloWorldService,然后执行helloWorld方法。

 

step-2-abstract-beanfactory-and-do-bean-initilizing-in-it

        step1中的bean是初始化好之后再set进去的,实际使用中,我们希望容器来管理bean的创建。于是我们将bean的初始化放入BeanFactory中。相比step1,

  1. BeanDefinition 类增加了 Class beanClass 和 String beanClassName属性,对应增加了 setter 和 getter 方法,重点关注 setBeanClassName 方法,这个方法加载名为“beanClassName”的类并执行其静态代码块,同时为属性 beanClass 赋值。
    	public void setBeanClassName(String beanClassName) {
    		this.beanClassName = beanClassName;
    		try {
    			this.beanClass = Class.forName(beanClassName);
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}
    	}
    

     

  2. BeanFactoryTest.java
    public class BeanFactoryTest {
    
    	@Test
    	public void test() {
    		// 1.初始化beanfactory
    		BeanFactory beanFactory = new AutowireCapableBeanFactory();
    
    		// 2.注入bean
    		BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setBeanClassName("us.codecraft.tinyioc.HelloWorldService");
    		beanFactory.registerBeanDefinition("helloWorldService", beanDefinition);
    
            // 3.获取bean
            HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
            helloWorldService.helloWorld();
    
        }
    }

    整体流程:

  3. 1、目标依旧:执行 HelloWorldService 的 helloWorld 方法,但是不直接 new HelloWorldService()

  4. 2、先 new 一个 BeanFactory,再 new 一个 BeanDefinition

  5. 3、但是,没有选择继续 new HelloWorldService,而是将 HelloWorldService 的全路径传入 setBeanClassName 方法中,由此得到这个类的 object(不是 instance)

  6. 4、在 beanFactory.registerBeanDefinition 的方法中,执行 beanDefinition.getBeanClass().newInstance() 方法,得到这个类的 instance。

  7. 5、然后从 BeanFactory 的 Map 中 get 到这个 BeanDefinition,然后执行 helloWorld 方法

step-3-inject-bean-with-property

与step2相比,这里主要为bean注入属性。我们选择将属性注入信息保存成PropertyValue对象,并且保存到BeanDefinition中。这样在初始化bean的时候,我们就可以根据PropertyValue来进行bean属性的注入。

  1. 1、改变 HelloWorldService.java,增加属性String text及 setText()方法。

  2. 2、BeanFactoryTest.java中添加了一段设置属性

    public class BeanFactoryTest {
    
    	@Test
    	public void test() throws Exception {
    		// 1.初始化beanfactory
    		BeanFactory beanFactory = new AutowireCapableBeanFactory();
    
    		// 2.bean定义
    		BeanDefinition beanDefinition = new BeanDefinition();
    		beanDefinition.setBeanClassName("us.codecraft.tinyioc.HelloWorldService");
    
    		// 3.设置属性
    		PropertyValues propertyValues = new PropertyValues();
    		propertyValues.addPropertyValue(new PropertyValue("text", "Hello World!"));
            beanDefinition.setPropertyValues(propertyValues);
    
    		// 4.生成bean
    		beanFactory.registerBeanDefinition("helloWorldService", beanDefinition);
    
    		// 5.获取bean
    		HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
    		helloWorldService.helloWorld();
    
    	}
    }

    3、AutowireCapableBeanFactory.java 中增加了一个applyPropertyValues方法,来进行属性赋值。

    public class AutowireCapableBeanFactory extends AbstractBeanFactory {
    
    	@Override
    	protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
    		Object bean = createBeanInstance(beanDefinition);
    		applyPropertyValues(bean, beanDefinition);
    		return bean;
    	}
    
    	protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {
    		return beanDefinition.getBeanClass().newInstance();
    	}
    
    	protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {
    		for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
    			Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
    			declaredField.setAccessible(true); //设置true,使得反射能访问私有变量
    			declaredField.set(bean, propertyValue.getValue());
    		}
    	}
    }
    

     

整体流程:

  1. 目标依旧:执行 HelloWorldService 的 helloWorld 方法,但是不直接 new HelloWorldService()。再加上一个小目标:为 HelloWorldService 的 text 属性赋值。
  2. 先 new 一个 BeanFactory,再 new 一个 BeanDefinition。
  3. 通过 Class.forName 得到 HelloWorldService 的 object(同时 将 bean 的 beanClassbeanClassName设置好了)。
  4. 将 PropertyValues 放入 BeanDefinition 的实例中。
  5. 得到 HelloWorldService 的 instance,将 PropertyValues 的属性值放入 instance 中,(将 bean 的propertyValues设置好了),在设置属性bean,完整的 bean 就此产生,通过 getBean()方法就能够拿到 HelloWorldService 的 instance 了,就可以调用参数/执行方法了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值