说一下我对Spring和Spring Ioc整体理解
1.Spring框架的整体理解
Spring是一个框架,在我们使用Spring框架开发流程中,所有的框架几乎都依赖于Spring。Spring帮我们起到了一个IOC容器的作用,用来承载我们整体的bean对象,它帮我们进行了整个对象从创建到销毁的整个生命周期的管理。在我们使用Spring的时候,可以使用配置文件,也可以使用注解的方式进行相关实现,当我们程序启动开始的时候,我们把配置文件或者注解定义好的那些bean对象转换成一个beanDefition,然后完成整个beanDefition的解析和加载过程。当我们获取到这些完整的beanDefition对象之后,对整个beanDefintion进行实例化操作,在进行实例化的时候,最简单的一种方式是通过反射的方式来创建对象bean(只是在堆里开辟了一个内存),但这没有完成后续一系列初始化操作,还会在后面实现awre接口的操作、包括实现一些初始化操作,包括我要实现AOP的操作的话,可能要执行一些beanPostProcessor操作。当然,在beanDefition的环节,也会执行一系列beanfactoryPostProcessor的操作来实现相关的扩展操作。当我们整体对象都创建完成之后,对象就可以直接调用了。
2.Spring Ioc整体理解
Ioc(inverse of control),中文称为控制反转。它是一种设计思想,而不是特指某个技术。所谓的控制反转,简单来说,我认为就是把对象的控制权由对象内部改为外部容器来控制,每个对象的生命周期(从产生到销毁)都由外部的容器来控制,这其实就是控制的反转。IOC实现主要是通过依赖查找和依赖注入两个方式来实现的。
比如有下面这个段代码:
User类:
public class User {
private Long userId;
private String userName;
private String password;
private UserInfo userInfo;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public UserInfo getUserInfo() {
return userInfo;
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
}
UserInfo类:
import java.util.Date;
public class UserInfo {
private String address;
private Date lastLoginTime;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
}
那么现在我的客户端要得到User对象,那么就应该这么做:
package com.donkey;
public class CLient {
public static void main(String[] args) {
//先实例化User对象
User user = new User();
//实例化UserInfo对象
UserInfo userInfo = new UserInfo();
//将userInfo对象实例化到user中
user.setUserInfo(userInfo);
System.out.println(user);
}
}
从这段代码我们可以看到,对象的创建以及对象之间的引用关系(注入)全部是由客户端来管理的,就是说谁用谁创建,谁用谁来管理。就好比我要吃面包,我不是从面包盒子里直接拿过来吃,而是要经过和面、面包造型、烤箱烤等一系列的加工过程,才能够吃上这个面包。
我们把上面的代码多一个简单的改造:
增加一个bean的配置文件:user-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 定义userInfo bean信息-->
<bean id="userInfo" class="com.donkey.UserInfo">
<property name="address" value="山东济南"/>
</bean>
<!-- 定义user bean信息,并且把userInfo注入到user中-->
<bean id="user" class="com.donkey.User">
<property name="userId" value="1" />
<property name="userName" value="zhangsan" />
<property name="userInfo" ref="userInfo"/>
</bean>
我们再看客户端:
package com.donkey;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CLient {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:user-context.xml");
User bean = beanFactory.getBean(User.class);
System.out.println(bean);
}
}
这里客户端想获取user对象,直接从Spring Ioc容器中取就行了,并且这个userInfo已经注入到了这个user中。这就是Spring Ioc最典型的一种应用。那么说到这里,我认为就算我们自己定义的简单工厂类、单例、消息都可以算作是一个Ioc的广义上的实现,即对象的整个管理全部交给了外部容器来处理,客户端只需要拿来用就行了。这也是好莱坞原则“不要打电话给我,我会打电话给你”。