- 1.spring使用转义符“&”来得到FactoryBean本身
- 2.区分FactoryBean和BeanFactory:在Spring种,所有的Bean都是由BeanFactory(也就是IOC容器管理的),但是对应FactoryBean而言,这个不是普通的Bean,而是能产生或修饰对象生成给工厂Bean
- 3.BeanFacroty接口
-
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException; Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }
- 4.编程式使用IOC容器
ClassPathResource res=new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
- 创建Ioc配置文件的抽象资源,这个抽象资源包括BeanDefinition的定义信息
- 创建一个BeanFactory,这里使用DefaultListableBeanFactory
- 创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefiniiton,通过一个回调配置给BEanFactory
- 通过XmlBeanDefinitionReader来完成解析,完成整个载入和注册Bean后,需要的Ioc容器就建立起来了。
6.通常使用FileSystemXmlApplicationContext的实现来说明ApplicationContext的设计原理
- 在FileSystemXmlApplicationContext种,ApplicationContext的主要功能已经在FileSystemXmlApplicationContext的基类AbstractXmlApplicationContext种实现了,所以FileSystemXmlApplicationContext只需要实现自身的两个功能:
-
//refresh函数载入BeanDefinition public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
//在BeanDefinitionReader的loadBeanDefinition中被调用 @Override protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); }
简单来说IOC容器的初始化是从refresh()方法来启动的,具体来说这个启动包括:
-
BeanDefinition的Resource定位
-
BeanDefinition的载入,把用户定义好的Bean表示成Ioc容器的内部的数据结构(BeanDefinition)
-
注册,向Ioc容器注册这些BeanDefinition,通过调用BeanDefinitionRegistry接口实现的
在这个方法中,我们可以看到FileSystemXmlApplicationContext的refresh()会去调用父类的refresh方法(),在refresh()中的obtainFreshBeanFactory()方法经过层层调用,最终会调用FileSystemXmlApplicationContext的getResourceByPath()方法
步骤:进入refresh(),再进入obtainFreshBeanFactor()方法,再进入refreshBeanFactory(),可以看到
protected final void refreshBeanFactory() throws BeansException {
//如果创建了BeanFactory,则销毁并关闭BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
//这里是创建持有的DefaultListableBeanFactory的地方同时调用
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//启动对BeanDefinition的载入,在载入的过程中定位资源,
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
createBeanFactory()方法会创建一个IOC容器供ApplicationContext使用,同时启动loadBeanDefinitions来载入,在载入的过程中定位资源,
先回到refresh()方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
//这里是在子类中启动refreshBeanFactory()的地方
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//设置BeanFactory的后置处理
postProcessBeanFactory(beanFactory);
//调用BeanFactory后置处理器,这些后置处理器是在Bean定义中向容器注册的
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean的后置处理器,在Bean创建过程中调用
registerBeanPostProcessors(beanFactory);
// 对上下文中的消息源进行初始化
initMessageSource();
//初始化上下文中的事件机制
initApplicationEventMulticaster();
//初始化其他特殊的Bean
onRefresh();
// 检测监听Bean并将这些Bean向容器注册
registerListeners();
// 实例化所以的(noon-lazy-init)单件
finishBeanFactoryInitialization(beanFactory);
// 发布容器事件,结束refresh过程
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
//销毁
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
在loadBeanDefinitions()方法中,会得到resource的inputStream,再得到解析xml的文档流对象(使用documentLoader完成),然后按照Spring定义的Bean的规则来对这个XML的文档树进行解析
总的来说,BeanDefinition的载入分成两部分,
①得到document对象(读取<bean>.读取<property>(若里面为list,则遍历解析)),
②按照Bean规则进行解析
在得到文档流对象后,完成对BeanDefinition的处理,处理的结果由BeanDefinitionHolder对象来持有(除了持有BeanDefinition对象外,还有Bean的名字,别名集合等),然后就向Ioc容器注册解析得到的BeanDefinition
具体的文档解析过程:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//这里取得<bean>元素走红定义的id,name和aliase属性的值
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//开始详细的解析
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
开始读取定义的<Bean>
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//这里只读取<bean>中设置由class名字的,然后载入到BeanDefinition中去
//注意,并不涉及对象的实例化,实例化是在依赖注入时完成的
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//生成需要的BeanDefinition对象,为Bean定义信息的载入做准备
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//对Bean元素进行解析,并设置description的信息
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//对各种<bean>元素的信息进行解析的地方
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析<bean>的构造函数设置
parseConstructorArgElements(ele, bd);
//解析<bean>的property设置
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
这里列举对property进行解析的例子:
//遍历property元素,再调用parsePropertyElement进行解析
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
解析某个property
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
//如果同一个Bean中已经由同名的property设置,那么起作用的只是第一个
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
//解析结果,封装到PropertyValue对象中,然后设置到BeanDefinitionHolder中
Object val = parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
取得property元素的值,也许是一个list或其他的
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element";
// Should only have one child element: ref, value, list, etc.
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!nodeNameEquals(node, META_ELEMENT)) {
// Child element is what we're looking for.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
subElement = (Element) node;
}
}
}
//判断property的属性是ref还是value,不允许同时存在ref和value
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
//如果是ref,创建RuntimeBeanReference,存放erf信息
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(ele));
return ref;
}
//如果是value,创建一个value的数据对象TypedStringValue 存放值
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
//对子元素进行解析
else if (subElement != null) {
return parsePropertySubElement(subElement, bd);
}
else {
// Neither child element nor "ref" or "value" attribute found.
error(elementName + " must specify a ref or value", ele);
return null;
}
}
对list进行解析,加入到target中,target的一个ManageList,除非对下一层子元素的解析
这样,XML文件中定义的BEanDefinition就被载入到Ioc容器了,并建立了数据映射
BeanDefinition再Ioc容器中的注册
这些BeanDefinition信息的使用map存储的,在DefaultListableBeanFactory中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
依赖注入:
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
//实际上获取Bean的地方,也是触发依赖注入的地方
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 先从缓存中取得Bean,处理那些已经被创建过的单例模式的bean,这种不需要重复创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//取得FactoryBean的生产结果
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//检查能否再当前的BeanFactory中取得所需的Bean,若取不到,则一直往双亲找
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//根据Bean的名字取得Beandefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//取得当前BEan的依赖Bean,递归调用直到没有任何依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 对创建的Bean进行类型检查,没问题则返回,这个Bean是包括了依赖关系的Bean
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
依赖注入步骤:
1.首先判断是否单例并且已经存在,若存在,则返回
2.若不存在,判断当前能否生产bean,不能则向双亲请求,直到找到能生产该bean的工厂
2.1判断当前bean是否有依赖,如果有则递归创建
2.2判断是单例,多例还是其他,然后创建bean
2.2.1判断是否实例化,是否能由类加载器载入
2.2.2判断是否bean有配置PostProcessor,有则返回一个proxy
2.2.3没有的话则去创建实例bean
2.2.3.1如果是单例,先清除缓存中同名的Bean
2.2.3.2创建bean
2.2.3.2.1判断是否能实例化
2.2.3.2.2使用工厂实例化,不行则使用构造函数实例化,(使用jdk动态代理或CGLIB)
2.2.3.2.3实例化成功后则设置参数,比如基类,回调方法等
2.2.3.3开始依赖注入
2.2.3.3.1autowire注入的处理,可以根据Bean的名字或类型
2.2.3.3.2对属性进行解析(如果是array和list需要遍历),再解析的过程中,如果有依赖,要去获取
2.2.3.3.2.1通过getPropertyValue取得Bean中对注入对象的引用,例如Array,List,Map,set等,然后注入,取得注入属性的 set方法,通过反射机制,注入进入
最后返回即可获得注入的bean
容器的实现通过IOC管理Bean的生命周期实现,提供了对生命周期内各个时间点的回调
简单介绍Bean的生命周期:
- Bean实例的创建
- 为Bean实例设置属性
- 调用Bean的(一系列,如果有的话)初始化方法
- 应用通过Ioc容器使用Bean
- 当容器关闭时,调用Bean的销毁方法
在调用Bean的初始化方法之前,会调用一系统的aware接口实现,把相关的BeanName,BeanClassLoader以及BeanFactory注入到Bean中去,接着调用inVokeInitMethods若实现了InitializingBean接口,会去调用agterPropertiesSet。若bean设置了initMethod,则会通过JDK的反射机制得到Method对象,之间调用Bean定义的初始化方法。
若定义了lazy-init属性,则在初始化的时候就预实例化
这里的预实例化巧妙的委托给容器,如果需要预实例化,则在refersh的过程中直接调用getBean去触发依赖注入
@autowire
以autowireByNam的实现过程来看
使用取得的当前Bean的属性名作为Bean的名字,向IOC容器索取bean,然后把得到的bean设置到当前Bean的属性中去
Bean对IOC容器的感知:
一般Bean不需要对ioc容器进行操作,但也可以通过aware接口来实现:
- BeanNameAware,可以在Bean中得到它在IOC容器中的bean实例名
- BeanFactoryAware,可以得到Bean所在的IOC容器,从而直接在Bean中使用ico容器的服务
- ApplicationContextAware,得到Bean所在应用上下文,从而直接在Bean中使用应用上下文服务
- MessageSourceAware,在Bean中得到消息源
- ApplicationEvenPublisherAware,在Bean中得到应用上下文的事件发布器,从而直接在Bean中发布应用上下文的事件
- ResourceLoaderAware,在Bean中得到ResourceLoader,从而在Bean中使用ResourceLoader加载外部的Resource资源