在上一篇文章中我们创建了第一个Spring程序,通过
ApplicationContext
加载了我们的bean.xml
文件,并且通过getBean
获取了我们的User
类的实体对象,那么我们并没有用new
关键词创建对象,究竟是怎么得到User
对象的?这里就用到了Spring的核心概念IoC
什么是IoC?
官方文档是这样解释的
This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) [1]principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern.
Spring是通过底层的一个工厂来加载我们自己编写的Java类,当我们有需要用到这个类的实例对象的时候,找Spring去拿就行了。
为什么要用IoC?
在传统Java项目开发中,如果我在另一个类中需要加载其他类的时候,必须通过
new
关键词去获取实例对象,再调用相关的方法,这样就会出现几个问题。- 项目的耦合度太高,如果我需要的另一个类重写了,例如类名等变了,那么我就需要去改当前类,极大的增加了开发难度,后期的大项目变成臃肿,难以维护。
- 如果又有新的类需要用到另一个类了,反复的
new
会导致内存的浪费,降低虚拟机的性能。
怎么用IoC?
Spring底层通过
BeanFactory
工厂来管理所有的类@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
user.print();
}
ApplicationContext
是BeanFactory
的一个实现,Spring主要通过这两个接口来加载我们的类,上述代码中可以直接替换为BeanFactory
也能实现bean
的加载,那我们为什么要用ApplicationContext
?两者的区别
BeanFactory
是供Spring内部使用的类,一般我们开发人员不会直接去使用他。在加载bean
的时候,不会直接创建对象,而是等到要使用对象的时候才会去加载ApplicationContext
是BeanFactory
的子类,功能更加强大,是开发中使用的类。在加载bean
的时候,会直接创建对象。我们只需要编写我们的配置文件
bean.xml
,再通过ApplicationContext
就可以使用了。通过注解使用beanFactory
@Test
public void test02(){
ApplicationContext context = new AnnotationConfigApplicationContext("demo");
User user = context.getBean("user", User.class);
System.out.println(user);
user.print();
}
我们还可以用
AnnotationConfigApplicationContext
这个类去加载我们的bean,需要告诉Spring要扫描哪个包下的类的,同时要在需要加载的类加上@Component
注解package demo.entity;
import org.springframework.stereotype.Component;
@Component
public class User {
public void print(){
System.out.println("我是user类");
}
}