一、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)