一、SpringIOC源码剖析
1.核心功能bean的配置与获取api
有以下四种
(来自精通spring4.x的p175)
常用的是前三种
第一种方式
<?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 指定class属性,通过构造方法创建Bean实例 --> <bean id="person" class="com.mao.gouzao.Person"> </bean> </beans> public static void main( String[] args ) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); System.out.println(ctx.getBean("person")); }
第二种方式
定义
@Service public class UserServiceImpl { public void test(){ System.out.println(666); } }
获取
@Autowired private static UserServiceImpl userService;
第三种方式
定义
@Configuration public class MainConfig { @Bean public Person person(){ return new Person(); } }
注意: 通过@Bean的形式是使用的话, bean的默认名称是方法名,若@Bean(value="bean的名称")那么bean的名称是指定的
去容器中读取Bean的信息(传入配置类)
获取
public static void main( String[] args ) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class); System.out.println(ctx.getBean("person")); }
2.如何实现的
1.基于Java类配置的实现方式源码分析
1.就执行了这两句代码
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class); System.out.println(ctx.getBean("person"));
先看看,打开构造器源码:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }
2.首先不急,主角儿AnnotationConfigApplicationContext 它有父类,因为类初始化顺序的关系,会先初始化父类,所以得看父类,一直看到最后父类为DefaultResourceLoader
DefaultResourceLoader,很明显是用来加载资源的,倒数第二个AbstractApplicationContext的无参构造中也是初始化一个加载资源相关:
Ok,再来看最后一个父类GenericApplicationContext了,父类默认初始化使用下面这个无参的
public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }
这里是创建了springioc体系中的一个重要的类DefaultListableBeanFactory,DefaultListableBeanFactory非常关键里面实现了ioc相关很多功能,可以提供给我们的AnnotationConfigApplicationContext使用(后面会看到)
3.ok父类都看完了,那就回到我们的主角儿AnnotationConfigApplicationContext了
我们来看它的构造器刚刚是什么代码(回归本身):
public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
就两行。
4.先看第一句this.reader = new AnnotatedBeanDefinitionReader(this);
进去
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); }
它再次调用自己的构造器
这里还涉及了一个方法getOrCreateEnvironment(registry)