前言

跳过废话,直接看正文

之前参与开发的几个spring的项目,用的版本都3.x, 最近忽然发现spring 5 都快上线了,于是赶紧去关注了下spring的最新动态。发现了spring-boot这个好东西(终于可以从各种错综复杂的xml配置文件中解放出来了!)。

在学习了目前最新的1.5.2.RELEASE版spring-boot官方文档之后,我决定仿照spring-boot的项目结构以及部分注解,写一个简单的ioc容器,一方面为了加深自己对ioc的理解,另一方面也为了以后在开发一些个人项目需要简单的使用一些自动装配功能时,可以直接使用这个ioc容器,而不用引入庞大的spring。


正文

在写正式代码之前,先写好测试代码,看看用这个ioc具体该做什么。

测试项目结构

  • sample
    • SampleApplication.java
    • runner
      • SampleApplicationRunner.java
    • model
      • BeanA.java
      • BeanB.java
      • BeanC.java

SampleApplication

作用

项目的启动入口。

代码
import com.clayoverwind.simpleioc.boot.SimpleIocBootApplication;
import com.clayoverwind.simpleioc.boot.SimpleIocApplication;

@SimpleIocBootApplication
public class SampleApplication{

    public static void main(String[] args) {
        SimpleIocApplication.run(SampleApplication.class, args);
    }
}
说明

这个启动模式是照搬了spring-boot的启动模式,将启动任务委托给SimpleIocApplication来完成。ioc容器将根据注解@SimpleIocBootApplication的相关配置自动扫描相应的package,生成beans并完成自动装配。(如果没有配置,默认扫描SampleApplication所在的package及其子package)

SampleApplicationRunner

作用

ioc容器启动的监听类, 这个类实现了SimpleIocApplicationRunner。因此,在ioc容器自动装配完成后,将自动调用SampleApplicationRunner中的run方法。

代码
import com.clayoverwind.simpleioc.boot.SimpleIocApplicationRunner;
import com.clayoverwind.simpleioc.context.annotation.SimpleAutowired;
import com.clayoverwind.simpleioc.context.annotation.SimpleBean;
import com.clayoverwind.simpleioc.context.annotation.SimpleComponent;
import com.clayoverwind.simpleioc.sample.model.BeanA;
import com.clayoverwind.simpleioc.sample.model.BeanB;
import com.clayoverwind.simpleioc.sample.model.BeanC;

@SimpleComponent
public class SampleApplicationRunner  implements SimpleIocApplicationRunner {

    @SimpleAutowired
    private BeanA beanA;

    @SimpleAutowired
    private BeanB beanB;

    @SimpleAutowired("beanC1")
    private BeanC beanC1;

    @SimpleAutowired("beanC2")
    private BeanC beanC2;

    @Override
    public void run(String[] args) throws Exception {
        beanA.print();
        beanB.print();
        System.out.println(beanC1.toString());
        System.out.println(beanC2.toString());
    }

    @SimpleBean("beanC1")
    private BeanC createBeanC1() {
        return new BeanC("I am bean c1!");
    }

    @SimpleBean("beanC2")
    private BeanC createBeanC2() {
        return new BeanC("I am bean c2!");
    }
}
说明
  • SimpleIocApplicationRunner 参考了Spring-boot中的ApplicationRunner。
  • @SimpleComponent作用于类,对应spring中的@Component
  • @SimpleAutowired只能作用于字段(实现相对简单),组合了spring中的@Autowired以及Qualifier的功能
  • @SimpleBean作用于方法,根据方法返回值来生成一个bean,对应spring中的@Bean

BeanA

说明

一个简单的bean。

代码
import com.clayoverwind.simpleioc.context.annotation.SimpleAutowired;
import com.clayoverwind.simpleioc.context.annotation.SimpleComponent;

@SimpleComponent
public class BeanA {
    private String content;

    @SimpleAutowired
    private BeanB beanB;

    public BeanA(){}

    public BeanA(String content) {
        this.content = content;
    }

    public void print() {
        System.out.printf("[BeanA].beanB = %s\n", beanB.toString());
    }
}

BeanB

说明

一个简单的bean。在这里可以看到,BeanA依赖BeanB,而BeanB也依赖BeanA,这就产生了一种依赖循环。这种依赖循环比较常见,因此ioc容器要能够解决这种问题。

代码
import com.clayoverwind.simpleioc.context.annotation.SimpleAutowired;
import com.clayoverwind.simpleioc.context.annotation.SimpleComponent;

@SimpleComponent
public class BeanB {
    private String content;

    @SimpleAutowired
    private BeanA beanA;

    public BeanB(){}

    public BeanB(String content) {
        this.content = content;
    }

    public void print() {
        System.out.printf("[BeanB].beanA = %s\n", beanA.toString());
    }
}

BeanC

说明

BeanC并没有加@SimpleComponent,因此ioc容器不会自动为该类生成一个bean。这个类的主要是用来测试@Bean
(见SampleApplicationRunner 中的createBeanC1()和createBeanC2())。

代码
public class BeanC {
    private String content;

    public BeanC(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "BeanC.content = " + content;
    }

}

后记

有了测试代码,接下来便要开始实现这个简单的ioc容器,详见下一篇博客。
完整代码参考:https://github.com/clayandgithub/simple-ioc

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐