spring-framwork-core-ioc
Spring-framwork-core-IoC
LinkSources:https://docs.spring.io/spring/docs/5.2.1.RELEASE/spring-framework-reference/core.html#beans-introduction
bean 三种实例化注册方式
-
xml实例化bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- class:哪个bean需要被实例化,就用哪个bean的路径
id:告诉spring被实例化这个bean叫什么名字-->
<bean class="com.lin.springcore.xmlRegisterBean.Cat" id="cat"></bean>
</beans>
-
注解@Component实例化bean
package com.lin.springcore.annoRegisterBean;
import org.springframework.stereotype.Component;
//@Component标识这个类,需要被实例化
@Component
public class dog {
}
-
java实例化bean
package com.lin.springcore.javaRegisterBean;
//需要被实例化的bean
public class Pig {
}
package com.lin.springcore.javaRegisterBean;
import org.springframework.context.annotation.Bean;
//注意:此处RegisterBeanConfig类上我并未使用@Configuration注解,是因为我使用的
// AnnotationConfigApplicationContext对象时,
//传递的是RegisterBeanConfig.class。否则,RegisterBeanConfig类必须也要使用xml方式
// 或@Component配置成bean。
public class RegisterBeanConfig {
//这个注解才是真正的java实例化bean的关键,可以指定多个value值,第一个往后,为别名
@Bean(value = {"pig", "pig2", "pig3"})
public Pig getPig() {
return new Pig();
}
}
-
Test 三种注解
ClassPathXmlApplication和AnnotationConfigApplicationContext
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("
classpath:xmlRegisterBean.xml");
Animal animal = context.getBean("Cat", Cat.class);
}
@Test
public void test2() {
ApplicationContext context = new AnnotationConfigApplicationContext(Dog.class);
Animal animal = context.getBean(Dog.class);
}
@Test
public void test3() {
ApplicationContext context = new AnnotationConfigApplicationContext(
RegisterBeanConfig.class);
Object getPig1 = context.getBean("getPig");
}
ClassPathXmlApplicationContext对象用来加载xml配置文件,AnnotationConfigApplicationContext用来加载一个类。spring通过抽象抽取了一个用户使用的对象ApplicationContext,此次ioc部分我们最常用的方法就是getBean()
ClassPathXmlApplicationContext有多个构造函数重载,这里提一种常见的ClassPathXmlApplicationContext(String... configLocations)参数接收可变长度的字符串,也就是说,ClassPathXmlApplicationContext可以同时加载多个xml配置文件。
AnnotationConfigApplicationContext也有多个构造函数重载,最常用的是AnnotationConfigApplicationContext(Class<?>... componentClasses)参数接收可变长度的Class类对象,可以同时加载多个配置对象类。
getBean()方法的可重载方式很多,接收一个字符串根据bean的id查询,接收Class根据类型查询,还可以同时接收id和class。
-
bean注册的位置
上边介绍的三种方式无论哪一种最终都会将pojo实例化到spring容器中。那么我们经常说的spring容器到底是什么?查看ApplicationContext对象。在spring上下文中有一个beanFactory对象,该对象实现类DefaultListableBeanFactory。依次再找父类AbstractAutowireCapableBeanFactory-->AbstractBeanFactory-->FactoryBeanRegistrySupport-->DefaultSingletonBeanRegistry中有一个Map,registeredSingletons这个Map就是用来存放所有单例模式的bean。关于bean的模式后边内容会说到。
-
ApplicationContext:
-->beanFactory
-->DefaultListableBeanFactory
-->AbstractAutowireCapableBeanFactory
-->FactoryBeanRegistrySupport
-->DefaultSingletonBeanRegistry
-->Map
-
选取哪一种方式合适?
以上三种实例化bean的方式,无论使用哪一种,最终的bean都会存到到registeredSingletons这个Map中。我们可以三种方式混着用,也可以只用一种方式。使用过springmvc框架的朋友一般都有过这样的配置。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>