目录
1.IoC容器
IOC: Inversion of Control,控制反转,是一种设计思想。
传统应用中,在对象中主动控制去直接获取依赖对象,这个是正转;反转则是由容器来创建及注入依赖对象,对象只是被动的接受依赖对象。
在spring框架中,Spring 通过IoC容器进行管理所有Java对象的实例化和初始化,控制对象与对象之间的依赖关系。
IoC管理的对象称为Bean,它与使用关键字new创建的java对象没有区别。所以我们可以理解为,IoC就是帮助我们将java对象的创建、管理及对象和对象之间的维护权交由spring框架进行负责。
IoC容器中使用map集合(map<String,Object>类型)存放Bean对象。
2.如何实现一个IoC容器(底层实现)
下面是IoC容器创建Bean的过程:
展开来说,IoC的底层实现如下:
- 首先通过注解或是xml文件的形式,定义Bean的相关信息(如id、name之类的),并通过相关抽象工具类(BeanDefinitionReader)读取Bean的定义信息,存入IoC容器中。
- 接着,通过CreateBeanFactory创建出一个Bean工厂;然后开始循环创建对象。因为容器中的Bean默认都是单例的,所以优先通过getBean, doGetBean从容器中查找;如果Bean不存在,通过createBean, deCreateBean方法,以反射的方式创建Bean;
- 最后,进行对象的属性填充(populateBean);并进行其他初始化操作(initializingBean)。
所以,根据以上原理,如何实现一个IoC容器?
先准备一个基本的容器对象,包含一些map结构的集合,用以存储具体的对象;
然后,进行配置文件的读取工作或者注解的解析工作,将需要创建的Bean对象都封装成BeanDefinition对象存储在容器中;
接着,容器将BeanDefinition对象通过反射的方式进行实例化;
实例化完成后,进行对象的初始化,也就是给类中的对应属性值就行设置(即依赖注入),完成对象的创建,变成一个完成的Bean对象,存储于容器的某个map结构中。
我们只能通过容器对象来获取对象,进行对象的获取和逻辑处理工作。
3.依赖注入
依赖注入:指在Spring创建对象的过程中,将对象依赖属性通过配置进行注入(类似于一个实体类Student中的属性包含另一个定义好的实体类Person,Person类就是注入到的Student中的类)。
依赖注入是对IoC的具体实现。
Spring中我们一般使用两个注解进行依赖注入:
- 1、@Autowired
- 2、@Resource
@Autowired注解:根据类型进行装配。主要有以下4种注入方式,其中,属性注入为最常用的注入方式:
//属性注入
@Autowired
private UserDao userDao;
//set注入
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//构造注入1
private UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao){
this.userDao = userDao;
}
//构造注入2
private UserDao userDao;
public UserServiceImpl(@Autowired UserDao userDao){
this.userDao = userDao;
}
上述代码皆为在ServiceImpl类中注入Dao类代码。需要注意的是, 如果只有一个有参构造方法时,@Autowired注解可以省略。即上述构造注入1、2中@Autowired注解都可以省略。
如果一个类型下有两个实现类,@Autowired注解无法正常根据类型进行注入,此时我们需要使用@Qualifier注解指定Bean的名称。
@Resource注解:根据名称进行装配,未指定name时,使用属性名作为name并根据属性名称进行注入,当name找不到时,会自动根据类型进行装配。
//无指定名称,根据类型注入
@Resource
private UserService userService;
//根据属性名称注入
@Resource
private UserService myUserService;
//根据指定名称注入
@Resource(name = "myUserService")
private UserService userService;
区别:@Resource注解是JDK拓展包中的注解,更具有通用性;@Auotwired是spring中的注解。@Resource只能使用在属性及set方法上。