blog
blog copied to clipboard
Spring IoC 原理简单分析
trafficstars
Spring IoC 原理简单分析
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");
}
}
在其中我们定义了 User 类的两个 Bean 实例化过程。然后我们调用 ApplicationContex.getBean("user2") 来得到 Bean 的值。结果是肯定的,我们得到了 "Pelin_li2" 的对象。
可以看到 @Bean 我们并没有定义 name 属性,默认的是方法名。
getBean() 调用过程
上边是简单的使用,下边先看下他们之间的关系图:

如果 debug 代码,可以看到大概的调用过程:
-
调用 AbstractApplicationContext.getBean(String name) 方法:
@Override public Object getBean(String name) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name); }其中,
getBeanFactory()方法由GenericApplicationContext.java实现,返回的是DefaultListableBeanFactory。即上述代码最终会调用:DefaultListableBeanFactory.getBean(String name) -
调用
AbstractBeanFactory.getBean(String name)方法(因为 DefaultListableBeanFactory 继承自这个 abstract 类):@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }可以发现,其调用了 doGetBean() 方法,我们看下此方法的实现:
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } //省略 }其中:
Object sharedInstance = getSingleton(beanName);通过此方法获得共享对象,看getSingleton()方法能够发现,IoC 容器最底层其实就是一个 ConcurrentHashMapbean = getObjectForBeanInstance(sharedInstance, name, beanName, null);这个方法主要是用来判断 Object 是否是FactoryBean的一个实例。