目录
2.Spring的BeanFactory与FacotryBean的区别
1.Spring Bean解析
Spring采用XML的方式配置,一个Bean的配置如下:
<bean id="druidDataSource" destroy-method="close" class="com.alibaba.druid.pool.DruidDataSource"> ... ... </bean>
在Spring的源码中,是通过org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition方法进行解析XML,从每一个<bean>的element的配置,生成一个BeanDefinitionHolder实例(含beanName,aliases,beanDefinition等属性),注册为BeanComponentDefinition实例并触发相关的Listener事件。相关源码如下:
//解析XML中的Element bean注册生成bean对象,然后触发相关监听事件
//例如解析: <bean id="druidDataSource" destroy-method="close" class="com.alibaba.druid.pool.DruidDataSource"> ... ... </bean>
//org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//这里注册bean对象到IOC容器中,最终存储到beanDefinitionMap实例中
//即: org.springframework.beans.factory.support.DefaultListableBeanFactory#beanDefinitionMap
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//发送bean创建事件,触发事件监听相关处理Listener
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
//解析Element生成BeanDefinitionHolder对象
// org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
/**
* Parses the supplied {@code <bean>} element. May return {@code null}
* if there were errors during parse. Errors are reported to the
* {@link org.springframework.beans.factory.parsing.ProblemReporter}.
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取ID配置属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取Name配置属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//XML的name属性是添加到别名中
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//Bean的唯一表示id作为beanName,唯一的标示
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
//beanName属性添加到别名中
checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
//如果没有配置beanName,则按照一定的规则生成beanName(className+#+16进制数据)
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.isTraceEnabled()) {
logger.trace("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;
}
2.Spring的BeanFactory与FacotryBean的区别
BeanFactory和FactoryBean都是位于org.springframework.beans.factory包下面,为Spring的容器工厂提供服务。
BeanFacotry是作为Spring容器的根接口,是建立容器的工厂类的基础接口协议,更多的是工厂的特性,看作Bean的容器(视为工厂)需要实现该接口,实现访问Bean容器可以通过该接口制定访问标准。其中最具有代表性的实现类是org.springframework.beans.factory.support.DefaultListableBeanFactory,该类是Spring默认的容器工厂类。该接口的源码如下:
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
/** 该接口是访问Spring的Bean容器的基础接口协议
* The root interface for accessing a Spring bean container.
* 访问Bean容器的基础视角
* <p>This is the basic client view of a bean container;
* further interfaces such as {@link ListableBeanFactory} and
* {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
* are available for specific purposes.
* 这个接口是由包含许多bean定义的对象实现的,每个bean定义都由一个字符串名唯一标识。
* <p>This interface is implemented by objects that hold a number of bean definitions,
* each uniquely identified by a String name. Depending on the bean definition,
* the factory will return either an independent instance of a contained object
* (the Prototype design pattern), or a single shared instance (a superior
* alternative to the Singleton design pattern, in which the instance is a
* singleton in the scope of the factory). Which type of instance will be returned
* depends on the bean factory configuration: the API is the same. Since Spring
* 2.0, further scopes are available depending on the concrete application
* context (e.g. "request" and "session" scopes in a web environment).
* BeanFactory是应用组件的注册中心
* <p>The point of this approach is that the BeanFactory is a central registry
* of application components, and centralizes configuration of application
* components (no more do individual objects need to read properties files,
* for example). See chapters 4 and 11 of "Expert One-on-One J2EE Design and
* Development" for a discussion of the benefits of this approach.
*
* <p>Note that it is generally better to rely on Dependency Injection
* ("push" configuration) to configure application objects through setters
* or constructors, rather than use any form of "pull" configuration like a
* BeanFactory lookup. Spring's Dependency Injection functionality is
* implemented using this BeanFactory interface and its subinterfaces.
*
* <p>Normally a BeanFactory will load bean definitions stored in a configuration
* source (such as an XML document), and use the {@code org.springframework.beans}
* package to configure the beans. However, an implementation could simply return
* Java objects it creates as necessary directly in Java code. There are no
* constraints on how the definitions could be stored: LDAP, RDBMS, XML,
* properties file, etc. Implementations are encouraged to support references
* amongst beans (Dependency Injection).
*
* <p>In contrast to the methods in {@link ListableBeanFactory}, all of the
* operations in this interface will also check parent factories if this is a
* {@link HierarchicalBeanFactory}. If a bean is not found in this factory instance,
* the immediate parent factory will be asked. Beans in this factory instance
* are supposed to override beans of the same name in any parent factory.
*
* Bean工厂实现应该尽可能支持标准Bean生命周期接口。全套初始化方法及其标准顺序如下:
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:
* <ol>
* <li>BeanNameAware's {@code setBeanName}
* <li>BeanClassLoaderAware's {@code setBeanClassLoader}
* <li>BeanFactoryAware's {@code setBeanFactory}
* <li>EnvironmentAware's {@code setEnvironment}
* <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)
* <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
* <li>MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)
* <li>ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)
* <li>ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
* <li>InitializingBean's {@code afterPropertiesSet}
* <li>a custom init-method definition
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
* </ol>
*
* <p>On shutdown of a bean factory, the following lifecycle methods apply:
* <ol>
* <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
* <li>DisposableBean's {@code destroy}
* <li>a custom destroy-method definition
* </ol>
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
* @since 13 April 2001
* @see BeanNameAware#setBeanName
* @see BeanClassLoaderAware#setBeanClassLoader
* @see BeanFactoryAware#setBeanFactory
* @see org.springframework.context.ResourceLoaderAware#setResourceLoader
* @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher
* @see org.springframework.context.MessageSourceAware#setMessageSource
* @see org.springframework.context.ApplicationContextAware#setApplicationContext
* @see org.springframework.web.context.ServletContextAware#setServletContext
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
* @see InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
* @see DisposableBean#destroy
* @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName
*/
public interface BeanFactory {
/**
* Used to dereference a {@link FactoryBean} instance and distinguish it from
* beans <i>created</i> by the FactoryBean. For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
//同于区分Bean的工厂类实例和Bean类实例本身,即&标示为工厂
String FACTORY_BEAN_PREFIX = "&";
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>This method allows a Spring BeanFactory to be used as a replacement for the
* Singleton or Prototype design pattern. Callers may retain references to
* returned objects in the case of Singleton beans.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
* @throws BeansException if the bean could not be obtained
*/
// 从工厂中获取一个Bean实例
Object getBean(String name) throws BeansException;
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>Behaves the same as {@link #getBean(String)}, but provides a measure of type
* safety by throwing a BeanNotOfRequiredTypeException if the bean is not of the
* required type. This means that ClassCastException can't be thrown on casting
* the result correctly, as can happen with {@link #getBean(String)}.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @param requiredType type the bean must match; can be an interface or superclass
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanNotOfRequiredTypeException if the bean is not of the required type
* @throws BeansException if the bean could not be created
*/
//从工厂中获取一个指定类型的Bean实例
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* @param name the name of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanDefinitionStoreException if arguments have been given but
* the affected bean isn't a prototype
* @throws BeansException if the bean could not be created
* @since 2.5
*/
//从工厂中获取带参数的构造函数的Bean实例
Object getBean(String name, Object... args) throws BeansException;
/**
* Return the bean instance that uniquely matches the given object type, if any.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
* @param requiredType type the bean must match; can be an interface or superclass
* @return an instance of the single bean matching the required type
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
* @throws BeansException if the bean could not be created
* @since 3.0
* @see ListableBeanFactory
*/
<T> T getBean(Class<T> requiredType) throws BeansException;
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
* @param requiredType type the bean must match; can be an interface or superclass
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanDefinitionStoreException if arguments have been given but
* the affected bean isn't a prototype
* @throws BeansException if the bean could not be created
* @since 4.1
*/
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
/**
* Return a provider for the specified bean, allowing for lazy on-demand retrieval
* of instances, including availability and uniqueness options.
* @param requiredType type the bean must match; can be an interface or superclass
* @return a corresponding provider handle
* @since 5.1
* @see #getBeanProvider(ResolvableType)
*/
//获取Bean的提供者,允许延迟按需获取实例
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
/**
* Return a provider for the specified bean, allowing for lazy on-demand retrieval
* of instances, including availability and uniqueness options.
* @param requiredType type the bean must match; can be a generic type declaration.
* Note that collection types are not supported here, in contrast to reflective
* injection points. For programmatically retrieving a list of beans matching a
* specific type, specify the actual bean type as an argument here and subsequently
* use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options.
* @return a corresponding provider handle
* @since 5.1
* @see ObjectProvider#iterator()
* @see ObjectProvider#stream()
* @see ObjectProvider#orderedStream()
*/
//获取Bean的提供者,允许延迟按需获取实例
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
/**
* Does this bean factory contain a bean definition or externally registered singleton
* instance with the given name?
* <p>If the given name is an alias, it will be translated back to the corresponding
* canonical bean name.
* <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
* be found in this factory instance.
* <p>If a bean definition or singleton instance matching the given name is found,
* this method will return {@code true} whether the named bean definition is concrete
* or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
* return value from this method does not necessarily indicate that {@link #getBean}
* will be able to obtain an instance for the same name.
* @param name the name of the bean to query
* @return whether a bean with the given name is present
*/
//从当前工厂以及父工厂中查询是否包含该单例的bean对象
boolean containsBean(String name);
/**
* Is this bean a shared singleton? That is, will {@link #getBean} always
* return the same instance?
* <p>Note: This method returning {@code false} does not clearly indicate
* independent instances. It indicates non-singleton instances, which may correspond
* to a scoped bean as well. Use the {@link #isPrototype} operation to explicitly
* check for independent instances.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return whether this bean corresponds to a singleton instance
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @see #getBean
* @see #isPrototype
*/
//判断当前的bean实例是否为单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* Is this bean a prototype? That is, will {@link #getBean} always return
* independent instances?
* <p>Note: This method returning {@code false} does not clearly indicate
* a singleton object. It indicates non-independent instances, which may correspond
* to a scoped bean as well. Use the {@link #isSingleton} operation to explicitly
* check for a shared singleton instance.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return whether this bean will always deliver independent instances
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 2.0.3
* @see #getBean
* @see #isSingleton
*/
//判断当前的bean是否是原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* Check whether the bean with the given name matches the specified type.
* More specifically, check whether a {@link #getBean} call for the given name
* would return an object that is assignable to the specified target type.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @param typeToMatch the type to match against (as a {@code ResolvableType})
* @return {@code true} if the bean type matches,
* {@code false} if it doesn't match or cannot be determined yet
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 4.2
* @see #getBean
* @see #getType
*/
//判断bean是否是指定的类型
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
/**
* Check whether the bean with the given name matches the specified type.
* More specifically, check whether a {@link #getBean} call for the given name
* would return an object that is assignable to the specified target type.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @param typeToMatch the type to match against (as a {@code Class})
* @return {@code true} if the bean type matches,
* {@code false} if it doesn't match or cannot be determined yet
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 2.0.1
* @see #getBean
* @see #getType
*/
//判断bean是否是指定的类型
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
/**
* Determine the type of the bean with the given name. More specifically,
* determine the type of object that {@link #getBean} would return for the given name.
* <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
* as exposed by {@link FactoryBean#getObjectType()}. This may lead to the initialization
* of a previously uninitialized {@code FactoryBean} (see {@link #getType(String, boolean)}).
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @return the type of the bean, or {@code null} if not determinable
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 1.1.2
* @see #getBean
* @see #isTypeMatch
*/
@Nullable
//根据bean的name属性获取bean的类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* Determine the type of the bean with the given name. More specifically,
* determine the type of object that {@link #getBean} would return for the given name.
* <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
* as exposed by {@link FactoryBean#getObjectType()}. Depending on the
* {@code allowFactoryBeanInit} flag, this may lead to the initialization of a previously
* uninitialized {@code FactoryBean} if no early type information is available.
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to query
* @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
* just for the purpose of determining its object type
* @return the type of the bean, or {@code null} if not determinable
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @since 5.2
* @see #getBean
* @see #isTypeMatch
*/
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
/**
* Return the aliases for the given bean name, if any.
* <p>All of those aliases point to the same bean when used in a {@link #getBean} call.
* <p>If the given name is an alias, the corresponding original bean name
* and other aliases (if any) will be returned, with the original bean name
* being the first element in the array.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the bean name to check for aliases
* @return the aliases, or an empty array if none
* @see #getBean
*/
//获取该name对应的bean的所有别名
String[] getAliases(String name);
}
而FacotryBean更多的是Bean的特性,这里是作为一个工厂实例来对外提供服务,更多的是工厂实例本身。本接口主要用于检测实例本身的特性。具体的参考源码如下:
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
//实现该接口的Bean是作为一个工厂,该工厂作为一个实例对外暴露服务。
//实现该接口的Bean可以作为一个普通的实例,是作为一个实例。即可作为单例,也可作为原型
/**
* Interface to be implemented by objects used within a {@link BeanFactory} which
* are themselves factories for individual objects. If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself.
*
* <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>
* A FactoryBean is defined in a bean style, but the object exposed for bean
* references ({@link #getObject()}) is always the object that it creates.
*
* <p>FactoryBeans can support singletons and prototypes, and can either create
* objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}
* interface allows for exposing more fine-grained behavioral metadata.
*
* <p>This interface is heavily used within the framework itself, for example for
* the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the
* {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for
* custom components as well; however, this is only common for infrastructure code.
*
* <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not
* supposed to rely on annotation-driven injection or other reflective facilities.</b>
* {@link #getObjectType()} {@link #getObject()} invocations may arrive early in the
* bootstrap process, even ahead of any post-processor setup. If you need access to
* other beans, implement {@link BeanFactoryAware} and obtain them programmatically.
*
* <p><b>The container is only responsible for managing the lifecycle of the FactoryBean
* instance, not the lifecycle of the objects created by the FactoryBean.</b> Therefore,
* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()}
* will <i>not</i> be called automatically. Instead, a FactoryBean should implement
* {@link DisposableBean} and delegate any such close call to the underlying object.
*
* <p>Finally, FactoryBean objects participate in the containing BeanFactory's
* synchronization of bean creation. There is usually no need for internal
* synchronization other than for purposes of lazy initialization within the
* FactoryBean itself (or the like).
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 08.03.2003
* @param <T> the bean type
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.aop.framework.ProxyFactoryBean
* @see org.springframework.jndi.JndiObjectFactoryBean
*/
public interface FactoryBean<T> {
/**
* The name of an attribute that can be
* {@link org.springframework.core.AttributeAccessor#setAttribute set} on a
* {@link org.springframework.beans.factory.config.BeanDefinition} so that
* factory beans can signal their object type when it can't be deduced from
* the factory bean class.
* @since 5.2
*/
//可用于设置Bean的属性,用于标示为Factory类型的类
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
/**
* Return an instance (possibly shared or independent) of the object
* managed by this factory.
* <p>As with a {@link BeanFactory}, this allows support for both the
* Singleton and Prototype design pattern.
* <p>If this FactoryBean is not fully initialized yet at the time of
* the call (for example because it is involved in a circular reference),
* throw a corresponding {@link FactoryBeanNotInitializedException}.
* <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}
* objects. The factory will consider this as normal value to be used; it
* will not throw a FactoryBeanNotInitializedException in this case anymore.
* FactoryBean implementations are encouraged to throw
* FactoryBeanNotInitializedException themselves now, as appropriate.
* @return an instance of the bean (can be {@code null})
* @throws Exception in case of creation errors
* @see FactoryBeanNotInitializedException
*/
@Nullable
//返回工厂创建的Bean的实例
T getObject() throws Exception;
/**
* Return the type of object that this FactoryBean creates,
* or {@code null} if not known in advance.
* <p>This allows one to check for specific types of beans without
* instantiating objects, for example on autowiring.
* <p>In the case of implementations that are creating a singleton object,
* this method should try to avoid singleton creation as far as possible;
* it should rather estimate the type in advance.
* For prototypes, returning a meaningful type here is advisable too.
* <p>This method can be called <i>before</i> this FactoryBean has
* been fully initialized. It must not rely on state created during
* initialization; of course, it can still use such state if available.
* <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return
* {@code null} here. Therefore it is highly recommended to implement
* this method properly, using the current state of the FactoryBean.
* @return the type of object that this FactoryBean creates,
* or {@code null} if not known at the time of the call
* @see ListableBeanFactory#getBeansOfType
*/
@Nullable
//返回工厂创建的Bean对象的类型
Class<?> getObjectType();
/**
* Is the object managed by this factory a singleton? That is,
* will {@link #getObject()} always return the same object
* (a reference that can be cached)?
* <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object,
* the object returned from {@code getObject()} might get cached
* by the owning BeanFactory. Hence, do not return {@code true}
* unless the FactoryBean always exposes the same reference.
* <p>The singleton status of the FactoryBean itself will generally
* be provided by the owning BeanFactory; usually, it has to be
* defined as singleton there.
* <p><b>NOTE:</b> This method returning {@code false} does not
* necessarily indicate that returned objects are independent instances.
* An implementation of the extended {@link SmartFactoryBean} interface
* may explicitly indicate independent instances through its
* {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean}
* implementations which do not implement this extended interface are
* simply assumed to always return independent instances if the
* {@code isSingleton()} implementation returns {@code false}.
* <p>The default implementation returns {@code true}, since a
* {@code FactoryBean} typically manages a singleton instance.
* @return whether the exposed object is a singleton
* @see #getObject()
* @see SmartFactoryBean#isPrototype()
*/
//判断是否是单例对象
default boolean isSingleton() {
return true;
}
}
3.Spring中常用的interface说明
1) org.springframework.boot.ApplicationRunner: 该接口主要适用于SpringApplication.run() -> callRunners方法中,在容器启动成功之后,会调用上下文所有实现了ApplicationRunner(封装了应用参数)和CommandLineRunner(应用原始传参)两个接口的实例,并触发相应的run方法,即可理解为应用启动的后置勾子hook。
2)org.springframework.boot.SpringApplicationRunListener: 该接口为SpringApplication应用的监听器接口,在org.springframework.boot.SpringApplication#run(java.lang.String...)方法中,启动之前调用starting接口,广播应用即将启动,当应用启动成功之后,调用started方法广播应用启动成功。
3)org.springframework.boot.Bootstrapper: 该接口为启动前的引导操作,主要适用于启动前的初始化操作。在org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)的构造方法中,通过读取META-INF/spring.factories文件中的配置,以加载对应的实例,完成初始化加载相关工作。
4)org.springframework.beans.factory.BeanFactory: Spring容器的根接口,是用于访问Spring容器的访问接口,即Bean的工厂类的接口规范,工厂类需要实现该接口。org.springframework.beans.factory.ListableBeanFactory接口是对该接口做了进一步扩展。
5)org.springframework.beans.factory.FactoryBean: 该接口作为工厂类的实例本身,作为普通Bean实例对外提供服务,该接口为Bean实例本身的规范,即有实例,有对象类型,还有是否为单例类型的标示。
6)org.springframework.beans.factory.InitializingBean: 该接口包含唯一afterPropertiesSet方法,当Bean的所有属性都通过BeanFactory完成设置之后,会触发该方法,并且仅触发一次。另一种方式,就是可以定义Bean的init方法,指定初始化方法也可以的。
7)org.springframework.beans.factory.DisposableBean: 该接口主要是包含一个destroy方法,该方法是用于当Bean生命周期结束时,销毁Bean相关的资源信息。该接口也可通过实现java.lang.AutoCloseable接口来进行资源回收,达到同样的目的。
8)org.springframework.beans.factory.BeanNameAware: 实现该接口主要适用于为了获取注入到Spring容器的Bean名称,bean的ID。
9)org.springframework.beans.factory.BeanFactoryAware: 实现该接口主要适用于为了获取注入对应的Bean的工厂类。
10)org.springframework.context.ApplicationContextAware: 该接口主要是与Spring上下文Context关联的,主要是用于在当前Bean中注入ApplcationContext上下文对象,通过该上下文可以访问Bean容器中的Bean的信息。
4.参考文章
1) https://www.cnblogs.com/xrq730/p/5721366.html