Spring源码解析:BeanFactory深入理解](讲得非常好)
彻底理解Spring容器和应用上下文
Spring核心容器:注册Bean、BeanDefinitionRegistry 简介
文章目录
-
Spring本质是一个bean工厂或bean容器,bean的创建都是通过beanFactory来实例化的。
依赖注入(DI)是BeanFactory生产bean时为了解决bean之间的相互依赖的一种技术而已。 -
BeanFactory【Bean工厂】是接口,是IOC容器的最顶层接口,为IOC容器的具体实现提供了规范。我们一般称BeanFactory为IoC容器,而称ApplicationContext为应用上下文。ApplicationContext是BeanFactory的子接口
BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory。 -
Spring的核心是容器,其提供了多个容器的实现方式,其中分为两种类型:
(1)实现BeanFactory接口
(2)实现ApplicationContext接口(我们通常称为应用上下文),它能提供更多的功能,例如解析配置文本信息。
常用的ApplicationContext实现:ClassPathXmlApplicationContext、FileSystemXMLApplicationContext、XmlWebApplicationContext、XmlWebApplicationContext
public class BeanFactoryTest {
public static void main(String[] args) throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:beans.xml");
BeanFactory bf = new XmlBeanFactory(res);
System.out.println("init BeanFactory.");
Car car = bf.getBean("car", Car.class);
System.out.println("car bean is ready for use!");
}
}
ClassPathXmlApplicationContext
ClassPathXmlApplicationContext:利用类路径下的XML文件来载入Bean定义的信息,需要正确设置classpath因为这个容器将在classpath里找bean配置
#加载单个配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
#同时加载多个配置文件
String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new ClassPathXmlApplication(locations);
FileSystemXMLApplicationContext
利用文件系统中的XMl文件来载入Bean定义的信息
对于FileSystemXmlApplicationContext:默认表示的是两种:
(1)没有盘符的是项目工作路径,即项目的根目录
(2)有盘符表示的是文件绝对路径
注意:如果要使用classpath路径,需要前缀classpath:
#加载项目根目录下的单个配置文件
ApplicationContext ctx = newFileSystemXmlApplicationContext("spring-config.xml");
#加载项目根目录下的多个配置文件
String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new FileSystemXmlApplicationContext(locations );
#加载指定路径下的配置文件
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:/project/bean.xml");
#加载classpath路径下的配置文件
ApplicationContext ctx = newFileSystemXmlApplicationContext("classpath:spring-config.xml");
XmlWebApplicationContext
- XmlWebApplicationContext用于web工程中从XML配置文件加载Bean定义的信息
- XmlWebApplicationContext初始化需要ServletContext,也就是需要web容器的前提下才能完成启动工作,可以通过在web.xml中配置自启动Servlet或Web容器监听来实现web容器的启动
- XmlWebApplicationContext,在默认情况下从/WEB-INF/applicationContext.xml中获取根上下文,但可以通过配置DispatcherServlet来修改默认配置文件的路径
<servlet>
<servlet-name>project</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
AnnotationConfigApplicationContext
- 使用AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下。
- AnnotationConfigApplicationContext的使用有两种,一种是指定java文件配置类,另一种是指定扫描路径。
- @Configuration可理解为用spring的时候xml里面的标签,@Bean可理解为用spring的时候xml里面的标签,如果@Bean没有指定name属性的情况下,Bean的名称就是@Bean标注的方法的方法名
public class JavaConfigTest {
public static void main(String[] arg) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
#注册bean配置类
ctx.register(AppConfig.class);
#刷新上下文
ctx.refresh();
Entitlement ent = (Entitlement)ctx.getBean("entitlement");
System.out.println(ent.getName());
System.out.println(ent.getTime());
Entitlement ent2 = (Entitlement)ctx.getBean("entitlement2");
System.out.println(ent2.getName());
System.out.println(ent2.getTime());
ctx.close();
}
}
@Configuration
public class AppConfig {
@Bean(name="entitlement")
public Entitlement entitlement() {
Entitlement ent= new Entitlement();
ent.setName("Entitlement");
ent.setTime(1);
return ent;
}
@Bean(name="entitlement2")
public Entitlement entitlement2() {
Entitlement ent= new Entitlement();
ent.setName("Entitlement2");
ent.setTime(2);
return ent;
}
}
public class Entitlement {
private String name;
private int time;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}