# 容器实现

# BeanFactory 实现的特点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
public class TestBeanFactory {
public static void main(String[] args) {
//创建基础Spring容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//创建BeanDefinition
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
//注册BeanDefinition
beanFactory.registerBeanDefinition("config", beanDefinition);
//遍历容器中所有的BeanDefinition
System.out.println("=============");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
//给BeanFactory添加后处理器 (bean工厂后处理器)
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
//再次遍历容器中的BeanDefinition
System.out.println("=============");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
//根据类型获取bean并遍历 调用每个beanFactoryPostProcessor的postProcessBeanFactory方法
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor ->
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory)
);
//再次遍历容器中的BeanDefinition
System.out.println("=============");
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
//此时发现并没有依赖注入, Bean1中的Bean2属性没有注入, 我们还需要Bean后处理器对依赖注入进行处理
// System.out.println(beanFactory.getBean(Bean1.class).getBean2());
//根据类型获取bean并遍历 调用每个BeanPostProcessor, 并让beanFactory添加这些beanPostProcessor
//添加代码 : 输出postProcessor顺序, 并尝试改变顺序, 判断其对@Autowired @Resource注解注入的影响
//postProcessor后处理器中有个order属性供DependencyComparator()判断, Autowired是最大值-2, Resource是最大值-3, 所以经过排序后, 采用了Resource注解注入
beanFactory.getBeansOfType(BeanPostProcessor.class).values()
.stream().sorted(beanFactory.getDependencyComparator()).forEach(beanPostProcessor -> {
System.out.println(">>>>>>>>>>" + beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});

//此语句使得容器预先实例化所有的单例beanDefinition, 不加此行代码的话, bean定义都是懒加载, 即需要用到时候才加载
beanFactory.preInstantiateSingletons();

//再次尝试获取Bean2 此时必须把上面获取Bean1的代码注释掉, 因为获取bean必须在添加bean后处理器之后
System.out.println("=============");
System.out.println(beanFactory.getBean(Bean1.class).getBean2());

//在Bean1中Inter变量中添加@Autowired注解, 观察注入的是Bean3还是Bean4
System.out.println("=============");
System.out.println(beanFactory.getBean(Bean1.class).getInter());
}
}

@Configuration
class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}

@Bean
public Bean2 bean2() {
return new Bean2();
}

@Bean
public Bean3 bean3() {
return new Bean3();
}

@Bean
public Bean4 bean4() {
return new Bean4();
}
}

interface Inter {
}

class Bean1 {
public static final Logger log = LoggerFactory.getLogger(Bean1.class);

public Bean2 getBean2() {
return bean2;
}

@Autowired
private Bean2 bean2;

@Autowired
@Resource(name = "bean4")
private Inter bean3;

public Inter getInter() {
return bean3;
}

public Bean1() {
System.out.println("Bean1构造函数");
}
}

class Bean2 {
public static final Logger log = LoggerFactory.getLogger(Bean2.class);

public Bean2() {
System.out.println("Bean2构造函数");
}
}

class Bean3 implements Inter {
public static final Logger log = LoggerFactory.getLogger(Bean3.class);

public Bean3() {
System.out.println("Bean3构造函数");
}
}

class Bean4 implements Inter {
public static final Logger log = LoggerFactory.getLogger(Bean4.class);

public Bean4() {
System.out.println("Bean3构造函数");
}
}
  • beanFactory 不会做的事 :

    1. 不会主动调用 beanFactory 后处理器

    2. 不会主动添加 Bean 后处理器

    3. 不会主动初始化单例

    4. 不会解析 beanFactory 还不会解析 ${}#{}

  • bean 后处理器会有排序的逻辑

# ApplicationContext 实现

  1. ClassPathXmlApplicationContext

    1
    2
    3
    4
    5
    6
    7
    private static void testClassPathXmlApplicationContext() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("b01.xml");
    for (String beanDefinitionName : context.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
    }
    System.out.println(context.getBean(Bean2.class).getBean1());
    }
  2. FileSystemXmlApplicationContext

    1
    2
    3
    4
    5
    6
    7
        private static void testFileSystemXmlApplicationContext() {
    FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("F:\\java\\study\\spring\\PrincipleOfSpring\\a01\\src\\main\\resources\\b01.xml");
    for (String beanDefinitionName : context.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
    }
    System.out.println(context.getBean(Bean2.class).getBean1());
    }

    以上两种实现方式都是将路径转交给 AbstractRefreshableConfigApplicationContext 来实现的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //读取xml文件之前
    System.out.println("读取xml之前============");
    for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
    }

    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.loadBeanDefinitions(new ClassPathResource("b01.xml"));

    System.out.println("读取xml之后============");
    for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
    }
  3. AnnotationConfigApplicationContext

    1
    2
    3
    4
    5
    6
    7
    private static void testAnnotationConfigApplicationContext() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
    for (String beanDefinitionName : context.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
    }
    System.out.println(context.getBean(Bean2.class).getBean1());
    }
  4. AnnotationConfigServletWebServerApplicationContext

    1
    2
    3
    public static void testAnnotationConfigServletWebServerApplicationContext() {
    AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
    }