Spring IoC 的最主要的目的是为了解耦。IoC 容器管理了一系列的 Bean,在服务启动的过程中,会通过配置文件(XML)、注解标识(@ Bean)来把需要管理的 Bean 实例化加载进来。这些 Bean 默认是单例的,也可以有其它的几种模式在下文会简单说明。
目前用到比较多的就是使用 @Bean 的办法来加载。
@ Bean 的使用
首先,我们写一个 Spring Boot 的应用:
@Controller
@EnableAutoConfiguration
public class Application {
@Bean
public User user1() {
User user = new User();
user.setAge(23);
user.setName("Pelin_li");
return user;
}
@Bean
public User user2() {
User user = new User();
user.setAge(23);
user.setName("Pelin_li2");
return user;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Resource
private ApplicationContext context;
@RequestMapping("/")
@ResponseBody
User home() {
return (User) context.getBean("user2");
}
}
Spring IoC 原理简单分析
Spring IoC 的最主要的目的是为了解耦。IoC 容器管理了一系列的 Bean,在服务启动的过程中,会通过配置文件(XML)、注解标识(@ Bean)来把需要管理的 Bean 实例化加载进来。这些 Bean 默认是单例的,也可以有其它的几种模式在下文会简单说明。
目前用到比较多的就是使用 @Bean 的办法来加载。
@ Bean 的使用
首先,我们写一个 Spring Boot 的应用:
在其中我们定义了 User 类的两个 Bean 实例化过程。然后我们调用 ApplicationContex.getBean("user2") 来得到 Bean 的值。结果是肯定的,我们得到了 "Pelin_li2" 的对象。
可以看到
@Bean
我们并没有定义 name 属性,默认的是方法名。getBean() 调用过程
上边是简单的使用,下边先看下他们之间的关系图:
如果 debug 代码,可以看到大概的调用过程:
调用 AbstractApplicationContext.getBean(String name) 方法:
其中,
getBeanFactory()
方法由GenericApplicationContext.java
实现,返回的是DefaultListableBeanFactory
。即上述代码最终会调用:调用
AbstractBeanFactory.getBean(String name)
方法(因为 DefaultListableBeanFactory 继承自这个 abstract 类):可以发现,其调用了 doGetBean() 方法,我们看下此方法的实现:
其中:
Object sharedInstance = getSingleton(beanName);
通过此方法获得共享对象,看getSingleton()
方法能够发现,IoC 容器最底层其实就是一个 ConcurrentHashMapbean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
这个方法主要是用来判断 Object 是否是FactoryBean
的一个实例。IoC 容器加载过程