The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.
翻译:
- Spring IOC容器就是一个org.springframework.context.ApplicationContext的实例化对象
- 这个容器负责
实例化
,配置
以及装配一个bean
从代码层次来看:Spring容器就是一个实现了ApplicationContext
接口的对象;
从功能上来看: Spring 容器是 Spring 框架的核心,是用来管理Spring bean的。容器将创建对象
,把它们连接在一起
,配置它们
,并管理他们
的整个生命周期从创建到销毁。
Spring容器通过我们提交的pojo类以及配置元数据产生一个充分配置的可以使用的系统
这里说的配置元数据,实际上我们就是我们提供的XML配置文件,或者通过注解方式提供的一些配置信息
这里的
Spring实例化
是指根据每个java类文件所生成的对应的BeanDefinition完成java bean的创建过程,这里的java bean是一个半成品,不能当作spring bean进行使用。官网 1.3.2. Instantiating Beans
Instantiation with a Constructor (通过使用java类的构造器进行实例化)
Instantiation with a Static Factory Method(通过静态工厂方法进行实例化)
Instantiation by Using an Instance Factory Method(通过实例工厂方法进行实例化)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1 获取要实例化的这个bean的class属性,确保beanDefinition中的beanClass属性已经完成解析
Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
// 对这个beanClass进行异常判断(跳过)
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName());
}
else {
// 2 使用beanDefinition中的supplier实例化这个bean(基本不使用)
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return this.obtainFromSupplier(instanceSupplier, beanName);
}
// 3 使用工厂方法(可能是静态工厂,也可能是实例工厂)实例化这个bean
else if (mbd.getFactoryMethodName() != null) {
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 4 通过构造函数实例化这个bean
else {
// 有参无参标识位
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized(mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// false,无参,使用无参构造器
if (resolved) {
return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
}
// true,有参,使用InstantiationAwareBeanPostProcessor#determineConstructorsFromBeanPostProcessors选择合适的有参构造器
else {
Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
ctors = mbd.getPreferredConstructors();
return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
} else {
return this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
}
}
@Configuration
@ComponentScan("pojo")
public class Config {
}
@Data
@Component
public class User {
int id;
String name;
}
public class ComponentMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
User user = applicationContext.getBean(User.class);
System.out.println(user);
}
}
debug:
return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd); // ctors == null
可以发现,代码执行的最后一行,当没有进行特殊的处理的时候,默认会使用无参构造函数进行对象的实例化
<?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">
<bean id="user" class="pojo.User">
<property name="id" value="28"></property>
<property name="name" value="mjoe"></property>
</bean>
</beans>
@Data
@Component
public class User {
int id;
String name;
}
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
}
打断点:
debug:
可以发现,beanName已经是xml文件中定义的id,此时ctors==null,将使用this.instantiateBean(beanName, mbd)
调用无参构造函数进行实例化。
public class MyUserFactory {
public static User getUser(){
User user = new User();
return user;
}
}
@Data
public class User {
int id;
String name;
}
<?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">
<!-- 通过静态工厂方法创建对象-->
<bean id="factoryUser" class="factory.MyUserFactory" factory-method="getUser"></bean>
</beans>
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
User factoryUser = (User) context.getBean("factoryUser");
System.out.println(factoryUser);
}
}
debug:
可以发现,Spring底层是通过factoryMethod的方法进行实例化对象的。Spring会在我们需要实例化的这个对象对应的BeanDefinition中记录factoryBeanName是什么(MyUserFactory
),同时会记录这个factoryBean中创建对象的factoryMethodName是什么(getUser()
),最后通过factoryBeanName获取一个Bean然后反射调用factoryMethod实例化一个对象(User
)
这里所说的通过静态工厂方式通过factoryBeanName
获取一个Bean,注意,这个Bean,不是一个FactoryBean。也就是说不是一个实现了org.springframework.beans.factory.FactoryBean接口的Bean
通过静态工厂方法这种方式特殊之处在于:包含这个静态方法的类(MyUserFactory
)不需要实例化,不需要被Spring管理。Spring的调用逻辑大概是:
public class MyUserFactory {
public static User getUser(){
User user = new User();
return user;
}
public User get(){
User user = new User();
user.setName("mjoeboyae");
return user;
}
}
@Data
public class User {
int id;
String name;
}
<?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">
<bean id="myFactoryBean" class="factory.MyUserFactory"></bean>
<!-- 通过实例工厂方法创建对象-->
<bean id="user" factory-bean="myFactoryBean" factory-method="get"></bean>
</beans>
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
}
debug:
经过默认构造器。
原文:https://www.cnblogs.com/mjoe/p/14994436.html