Spring ioc原理
spring基础使用
Spring概念
下载:http://www.springsource.org/download
Spring用于解决具有依赖关系的对象创建问题。
例如有类Manager和类UserDao
public class Manager {
private UserDao userDao;
public Manager(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
this.userDao.save();
}
}
public class UserDao {
public void save() {
System.out.println("------------UserDao.save()-------------");
}
}
则在创建Manager对象时必须首先创建UserDao对象,将它作为参数传递给构造方法,叫做Manager依赖于UserDao。实际业务中UserDao还可能依赖与其他类,如果都手工创建则很不方便,有改动时代码改动量会很大。可以在Spring的applicationContext.xml文件中配置依赖关系,这样创建Manager时,它所依赖的对象就会自动创建,叫做依赖注入。
spring配置
1、加入spring的库
* SPRING_HOME/dist/spring.jar
* SPRING_HOME/lib/jakarta-commons/commons-logging.jar
* SPRING_HOME/lib/log4j/log4j-1.2.14.jar
2、拷贝spring配置文件applicationContext.xml和log4j.properties到src下,这两个配置文件放在spring的示例jpetstore中,
SPRING_HOME/samples/jpetstore/war/WEB-INF下。
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="UserDao" class="com.aostaryh.dao.UserDao"/>
<bean id="Manager" class="com.aostaryh.manager.Manager">
<constructor-arg ref="UserDao">
</bean>
</beans>
bean 的id是唯一标识,不能有重复,class指定对应的类。
constructor-arg属性表明创建Manager时Spring将自动创建ref="UserDao"对应的bean id的对象作为参数传入。
如果Manager不将UserDao作为构造函数,而是用setUserDao方法来设置,则可以把<constructor-arg ref="UserDao">改为
<property name="userDao" ref="UserDao"/>
表示在创建完Manager对象后,调用setUserDao方法将UserDao的对象设置进去。
客户端调用:
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
Manager manager = (Manager)factory.getBean("Manager");
manager.save();
BeanFactory是一个接口ClassPathXmlApplicationContext的很多层父类已经是对它实现,其中就有ApplicationContext,因此用ApplicationContext factory声明也可以。
applicationContext.xml可以有多个,
* 构造new ClassPathXmlApplicationContext("applicationContext.xml")时参数可以传入一个字符串数组.
* spring在读取时会自动将几个文件的bean id内容合并。也可以这样写new ClassPathXmlApplicationContext("applicationContext-*.xml")用*模糊匹配加载xml。
* sping默认在加载配置文件时将所有bean创建并注入,可以配置让它用到哪个bean创建那个bean,方法:在beans标签中加入属性default-lazy-init="true",默认为false
普通属性注入
applicationContext.xml文件中 :
* 注入引用采用ref,有两种写法
<property name="userDao" ref="UserDao"/>
或者
<property name="userDao">
<ref bean=" UserDao "/>
</property>
* 注入字符串或数字采用value,有两种写法
<property name="userDao" value="Hello"/>
或者
<property name="userDao">
<value>Hello</value>
</property>
* 注入list对象或者数组采用list
<property name="listValue">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
* 注入set采用set
<property name="setValue">
<set>
<value>set1</value>
<value>set2"</value>
</set>
</property>
* 注入map采用map
<property name="mapValue">
<map>
<entry key="key1" value="v1"/>
<entry key="key2" value="v2"/>
</map>
</property>
由此可以看出,用spring可以代替自己写程序读取xml文件。spring能将配置的xml内容读取出来。
自定义属性注入
用户自定义属性和很多其他属性(例如将"2008-05-05"注入到java.util.Date类型的属性)在注入时是无法直接注入的,因为spring并不能转换所有的类型,这就需要用户自定义转换规则。
spring在遇到无法直接转换的属性时(例如将"2008-05-05"注入到java.util.Date类型),
<property name="date">
<value>2009-05-05</value>
</property>
这时会去找
class="org.springframework.beans.factory.config.CustomEditorConfigurer"
的bean,这个就是用户自定义属性的类,然后找到它的map属性customEditors,看其中是否有key值和所需要的类型一致的entity(例如key="java.util.Date"就是一个符合的entity),找到符合的entity,就用其中的value值(或bean值)的类创建一个对象。例如:
<bean id="CustomEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<bean class="com.spr.userpropertyedit.UserPropertyEdit"/>
</entry>
</map>
</property>
</bean>
其中UserPropertyEdit类是用户写的,它继承了java.beans.PropertyEditorSupport,例如:
public class UserPropertyEdit extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(text);
} catch (ParseException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
this.setValue(date);
}
}
其中的方法setAsText(String text)是覆写方法,spring会自动创建这个对象,并且调用这个方法,将value标签内的字符串"2009-05-05"作为参数传入,然后将这个类的value属性作为注入值,因此在这个方法中要用setValue(Object object)来设置返回作为注入的值。
SimpleDateFormat是日期处理类,创建对象时,可以将格式参数字符串,例如"yyyy-MM-dd"作为构造函数参数传入。它的parse(String s)返回Date类型对象。
公共属性注入
为减少注入时的重复书写,可以定义公共属性注入,需要的就集成它,例如:
<bean id="beanAbstract" abstract="true">
<property name="id" value="222"/>
<property name="name" value="TFC"/>
</bean>
<bean id="bean3" class="com.bjsxt.spring.Bean3" parent="beanAbstract">
<property name="name" value="KKK"/>
<property name="password" value="666666"/>
</bean>
<bean id="bean4" class="com.bjsxt.spring.Bean4" parent="beanAbstract"/>
其中beanAbstract加了属性abstract="true"表示其为公共属性bean,bean3、bean4继承了beanAbstract的property定义,减少了重复书写,但子bean中如果也定义了和父bean相同的属性,则会覆盖父bean的。例如bean3的name。
spring Bean的作用域
<bean id="beana" class="com.bjsxt.spring.Beana" scope="prototype"/>
scope可以取值:
* singleton:每次调用getBean的时候返回相同的实例
* prototype:每次调用getBean的时候返回不同的实例
默认singleton
根据名称和类型自动装配
Spring在装配属性时可以不用定义属性的装配规则,而采用根据bean的名称或类型自动查找一致的类生成对象来装配。
例如在beans标签里加上
default-autowire="byName"就能根据名称自动装配
但不推荐使用自动装配,因为这样从配置文件中就很难看出类之间的对应关系。
ioc原理分析
接口关系
简化关系:
BeanFactory是bean容器的顶级接口,定义了一些bean的基本操作。
如:
//这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。
Object getBean(String name, Class requiredType) throws BeansException;
//这里提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//这里根据bean名字得到bean实例,并同时判断这个bean是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//这里得到bean实例的Class类型
Class getType(String name) throws NoSuchBeanDefinitionException;
//这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
BeanFactory的三个子接口是:ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory。(简称HAL)
DefaultListableBeanFactory编程式方式使用ioc
BeanFactory-ConfigurableListableBeanFactory-DefaultListableBeanFactory是ioc的核心继承路线,其中DefaultListableBeanFactory是一个ioc容器的基础实现,它实现ioc的核心功能,后面的ApplicationContext等接口的实现都是在对象里面放了一个DefaultListableBeanFactory成员变量,getBean等操作都会DefaultListableBeanFactory对应的方法。如:
通过编程式方式使用DefaultListableBeanFactory:
ClassPathResource resource = new ClassPathResource("a.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
B b = (B)factory.getBean("b");
XmlBeanDefinitionReader创建时放入factory作为参数,然后通过loadBeanDefinitions读取resource即完成初始化。
resource是配置文件路径的封装,也就是用来定位资源位置的。
BeanDefinition
所有的bean都会封装成BeanDefinition的形式放入ioc容器,Beandefinition是一个接口,它提供了操作bean的公共方法:
如:
很多都是配置文件里面bean标签的属性。
ApplicationContext对Beanfactory的扩展
ApplicationContext继承了ListableBeanFactory、HierarchicalBeanFactory的同时继承EnvironmentCapable, MessageSource, ApplicationEventPublisher, ResourcePatternResolver等接口,使其具有加载资源、监听事件等能力。ApplicationContext虽然继承了Beanfactory,但它的实现类并非直接实现getBean等BeanFactory中的方法,而是在里面放了一个DefaultListableBeanFactory作为成员变量,实际的bean对象也是放在DefaultListableBeanFactory这个容器里面的。例如BeanPostProcesser扩展的可以在bean创建前后执行特定代码,也就是在操作DefaultListableBeanFactory成员变量的getBean前后加事件的方式实现。
ApplicationContext的子接口有ConfigurableApplicationContext、WebApplicationContext2个(简称WC),而它们的最终实现有3个:ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext. (简称CFX)
FileSystemXmlApplicationContext初始化流程分析
初始化主要做的事就是读取spring的bean配置文件,转换为BeanDefinition的形式,放到一个ConcurrentHashMap里。
FileSystemXmlApplicationContext的使用,如:
BeanFactory beanFactory = new FileSystemXmlApplicationContext("src/main/resources/a.xml");
// BeanFactory beanFactory = new FileSystemXmlApplicationContext("d:/b.xml");
System.out.println(beanFactory.containsBean("ttt1"));
System.out.println(beanFactory.getType("ttt1"));
它的构造函数:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
最终调用了AbstractApplicationContext的refresh()方法
通过前面的编程式使用ioc可以看出,这里需要创建一个XmlBeanDefinitionReader,并且以本对象的DefaultListableBeanFactory成员变量作为参数传入,创建Resource对象(ResourceLoader负责将String类型的路径转化为Resource对象),然后调用XmlBeanDefinitionReader的loadBeanDefinitions(resource)载入spring的bean配置,加载bean。
BeanDefinition资源定位
也就是创建Resource资源,通过ResourceLoader的getResource(String location)将文件路径解析成Resource的过程。根据不同的location类型(如classpath的,文件路径形式的等),Resource也可以分为不同的形式,如ClassPathResource、FileSystemResource等。
这一步在DefaultListableBeanFactory使用中是用户手动创建的,在ApplicationContext使用中是由spring创建的。
跟踪方法:
入口是AbstractRefreshableApplicationContext类的refreshBeanFactory()方法。
这里可以看出确实是DefaultListableBeanFactory
refreshBeanFactory()方法首先将原来的beanFactory销毁,然后创建新的,最后复制给本对象的成员变量。
然后是创建XmlBeanDefinitionReader,调用它的loadBeanDefinitions方法。
不过这里的参数不是Resource,而是String类型的,需要做转换:
可以看出这里是ResourceLoader负责将路径转换为Resource,其实就是根据不同的路径类型创建不同的Resource对象,如ClassPathResource就是将classpath:前缀去掉作为构造参数创建ClassPathResource对象。
BeanDefinition资源载入
资源载入和注册都在XmlBeanDefinitionsLoader的loadBeanDefinitions方法中进行,因此资源载入和注册是DefaultListableBeanFactory要进行的操作,而不是ApplicaionContext特有的操作。
资源载入也就是解析定位到的spring配置文件,将其解析成BeanDefinitionHolder的形式,载入到ioc容器中(此时还没有注册到ioc容器的map上)。
跟踪代码:
此时将Resource资源以io流的方式取出,为读取文件做准备。
DocumentLoader负责读取配置文件,以Document的形式供后面的解析使用。
最终是BeanDefinitionParserDelegate负责解析Document的Element。
这里上面一步是解析Element具体过程,下面一步就是将BeanDefinitionHolder的BeanDefinition注册到ioc容器的map。
这就是BeanDefinitionParserDelegate解析Element的具体过程,spring初始化经常看到的几种异常类型在这里都有声明。
(引用:refresh()方法的目的是加载或刷新bean的配置(xml、properties等)。
主要步骤是:读取配置、加载bean、注册bean到beanFactory、初始化事件监听。)
BeanDefinition注册
就是将BeanDefinition放入到ioc的ConcurrentHashMap里
这里首先检查是否已经有该BeanDefinition,如果有,判断该BeanDefinition是否允许覆盖,如果不允许,则抛异常,允许则覆盖。最后将BeanDefinition放入到ioc的ConcurrentHashMap里。
getBean创建Bean对象和依赖注入
创建Bean对象是由getBean方法触发的,它会查找到对应BeanDefinition,然后创建Bean对象,并且会自动创建所依赖的bean,设置到对应的属性上。
首先到单例bean的缓存中查找bean,如果找到就使用
可以看出,单例bean实例是以beanName为key放到一个HashMap中的。
这个ObjectFactory其实就是FactoryBean,使用工厂模式,通过getObject()方法取得目标bean对象的实例。
如果本容器里没有找到BeanDefinition配置,则将创建bean的任务交给父容器。
取出所依赖的beanDefinition,然后通过getBean触发依赖的beanDefinition的实例化。
调用createBean方法创建bean,传入了BeanDefinition作为参数。
实际调用到了doCreateBean
createBeanInstance负责创建bean对象,populateBean负责依赖注入。
进入到createBeanInstance里面:
进入populateBean方法里面:
这里就是设置属性的地方。
spring的前置、后置处理器
BeanFactoryPostProcessor和BeanPostProcessor
BeanFactoryPostProcessor是一个接口,只有一个方法
将实现BeanFactoryPostProcessor的类作为bean配置到spring中。spring创建beanfactory时会自动回调postProcessBeanFactory方法。用于控制BeanDefinition的生成。
BeanFactoryPostProcessor可以有多个实现,spring创建beanfactory会依次调用每个类的postProcessBeanFactory方法。
如:
BeanPostProcessor与BeanFactoryPostProcessor类似它也是一个接口,里面有2个方法,只不过它是控制bean对象的生成,在bean对象生成前和生成后回调。
如:
BeanFactoryPostProcessor的应用
创建可以获取容器bean的SpringUtils
由于BeanFactoryPostProcessor的回调方法会传入beanFactory,因此可以写一个SpringUtils实现这个接口,getBean时去调用beanFactory的getBean取得spring的bean对象。
如:
public class SpringUtils implements BeanFactoryPostProcessor {
private static BeanFactory beanFactory;
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
public static Object getBean(String beanName) {
return beanFactory.getBean(beanName);
}
}
设置spring可读取远程配置文件
例子:spring配置文件中,远程读取properties配置
默认spring配置文件中加载properties只能是本地文件,可以通过实现BeanFactoryPostProcessor接口扩展,使其加载配置从远程读取。
1、实现BeanFactoryPostProcessor 接口,会被Application contexts自动发现
2、BeanFactoryPostProcessor 仅仅对 bean definitions 发生关系,不能对bean instances 交互,对bean instances 的交互,由BeanPostProcessor的实现来处理
3、PropertyResourceConfigurer 是BeanFactoryPostProcessor的一个典型的实现
只要继承PropertyResourceConfigurer ,同时实现InitializingBean接口即可。
MyFilePlaceHolderBeanFactoryPostProcessor.java:
package com.tests;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.support.PropertiesLoaderUtils;
public class MyFilePlaceHolderBeanFactoryPostProcessor extends PropertyPlaceholderConfigurer implements InitializingBean {
public void afterPropertiesSet() throws Exception {
List<Properties> list = new ArrayList<Properties>();
// 此处模拟从远程获取配置信息
Properties p = PropertiesLoaderUtils.loadAllProperties("config.properties");
list.add(p);
// 设置远程取得的List<Properties>列表
setPropertiesArray(list.toArray(new Properties[list.size()]));
}
}
UserService.java:
package com.tests;
public class UserService {
public UserService() {
System.out.println("UserService 构造函数 ");
}
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
System.out.println("UserService setUsername " + username);
this.username = username;
}
public void setPassword(String password) {
System.out.println("UserService setPassword " + password);
this.password = password;
}
@Override
public String toString() {
return "UserService [username=" + username + ", password=" + password + "]";
}
}
Test.java
package com.tests;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:a.xml");
UserService userService = applicationContext.getBean(UserService.class);
String password = userService.getPassword();
applicationContext.destroy();
System.out.println(password);
}
}
a.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="user" class="com.tests.UserService">
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
<bean id="myFactoryPostProcessor" class="com.tests.MyFilePlaceHolderBeanFactoryPostProcessor" />
</beans>
config.properties
username=kkk
password=123456
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>tests</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Ts</name>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.13.RELEASE</version>
</dependency>
</dependencies>
</project>
调用入口:
InitializingBean
接口方式实现
InitializingBean是一个接口,只有一个方法:afterPropertiesSet
使用方式是bean直接继承这个接口,实现它的方法,afterPropertiesSet会在依赖注入完成后被回调。
如:
B依赖了C,B实现了InitializingBean接口,第一次输出c=null是因为此时B只是创建了对象,还没有完成依赖注入,c还是null,第二次输出的c不为null是因此在afterPropertiesSet方法输出,此方法在依赖注入完成后才被调用。
afterPropertiesSet与BeanPostProcessor的调用顺序如下:
postProcessBeforeInitialization
afterPropertiesSet
postProcessAfterInitialization
配置方式实现
接口方式使bean跟spring绑定了,必须实现InitializingBean接口,不太好。可以将初始化方法配置到bean标签的init-method属性中,摆脱对InitializingBean接口的依赖,如:
同理,在bean销毁的时候,也可以有回调方法,对应bean标签的destroy-method属性,如:
源代码分析
可以看出initializeBean是在populateBean之后调用的,因此是在依赖注入完成以后才执行。
Aware接口
Aware是个空接口,其下有很多子接口
在spring中,这些接口的实现类的实现方法会被spring回调。
BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的回调
其中BeanNameAware、BeanClassLoaderAware、BeanFactoryAware的实现类在bean完成依赖注入以后都会被自动回调方法:
ApplicationContextAwareProcessor的回调
而ApplicationContextAware等几个子接口实现类的方法被回调则是因为ApplicationContextAwareProcessor的缘故
而ApplicationContextAwareProcessor的加载则是在AbstractApplicationContext的refresh方法里
ServletContextAwareProcessor的回调
与ApplicationContextAwareProcessor类似,只不过ServletContextAwareProcessor不是在prepareBeanFactory设置,而是在下面一个方法postProcessBeanFactory设置的。
Web容器中使用的是XmlWebApplicationContext,在它的父类AbstractRefreshableWebApplicationContext中实现了postProcessBeanFactory方法,而这个方法也是refresh回调的。
使用测试
这里自动回调了setBeanName方法。
lazy-init属性
bean的Lazy-init属性默认为false,也就是在初始化完成以后就会自动创建singleton的bean,而不需要等到使用的时候用户去getBean时才创建。
ps:lazy-init也只是对singleton的单件bean起作用,因为多实例的bean每次使用都需要创建新对象。
源代码如下:
FactoryBean
FactoryBean是一个接口,用户工厂模式,里面有一个重要方法getObject(),通过这个方法取得真实的bean对象。
源代码:
注解方式使用 (autowiring的实现)
使用注解方式可以减少配置,spring配置文件声名略有不同:
a.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"
default-autowire="byName">
<context:component-scan base-package="com.test.springioc" />
</beans>
其中context:component-scan表示扫描bean包的根路径
@service表示这是一个spring的bean
@autowired表示自动装配的属性。
@PostContruct修饰方法等价于配置的init-method属性,表示依赖注入完成以后执行的初始化方法。
输出的c不为null,说明注入成功了
autowiring注入实现过程分析:
在populate()方法依赖注入时,会检查autowiring注解的属性,然后通过属性名字创建bean,注入到属性中。
根据名称或者类型装配。
创建bean,设置到对应属性。
bean的依赖检查
populatebean在依赖关系注入前,会进行检查,确保BeanDefinition的依赖关系正确:
扩展点:
BeanFactoryPostProcessor
创建BeanFactory时调用
BeanPostProcessor
创建Bean时调用
InitializingBean
创建Bean时调用
DisposableBean
销毁Bean时调用
FactoryBean
用户可以自定义的Bean
浙公网安备 33010602011771号