Spring Source code parsing, spring source code
I don't know why I looked at the source code of Spring. What impressed me most was Spring's abstract concept. So I learned the interface first.
BeanFactory is the basis for implementation of Spring IOC. A series of interfaces are defined here. Through the learning of these interfaces, we can get a general idea of how to work with each interface in BeanFactory system.
It lays the foundation for learning specific implementations. After all, the logic here is complicated and involves many concepts.
BeanFactory is the root interface of the Spring bean container. It provides APIs for obtaining beans, including beans, singleton and prototype, bean type and bean alias.
-- AutowireCapableBeanFactory adds integration with other framework functions. If WebWork is integrated, you can use Spring to manage Actions and other functions.
-- HierarchicalBeanFactory provides the access function of the parent container
-- ConfigurableBeanFactory, such as name, provides the factory configuration function, a lot of dazzling APIs
-- Aggregator ablelistablebeanfactory, which provides parsing, modification of bean definitions, and initialization Singleton.
-- ListableBeanFactory provides the bean instance enumeration function in the container. instances in the parent container are not considered here.
Do we think of the interface isolation principle in the Design Pattern principle?
Interface Segregation Principle (ISP): the client should not depend on the Interface it does not need; the dependency between classes should be established on the smallest Interface
If you are interested in this, contact du Niang or take a look at thisSix principles of design mode (4): interface isolation principle
The following system is clearly defined here:
Root Interface BeanFactory (Basic container)
Layer 2: third-party integration, inheritance system, and bean Traversal
Layer 3: Configuration
Layer 4: configuration + Iteration
Next, let's take a look at each interface (by the way, the directory ):
1. BeanFactory
2. AutowireCapableBeanFactory
3. HierarchicalBeanFactory
4. ListableBeanFactory
5. ConfigurableBeanFactory
6. ConfigableListableBeanFactory
1. BeanFactory
BeanFactory is the root interface of the Spring bean container.
Every bean is identified by bean name of the string type. The design mode Singleton is provided here, and the prototype replacement is implemented.
If the bean name is configured as a Singleton, only one instance is obtained in the application. If the bean name is configured as a prototype, the attributes can be instantiated and filled (based on the user's configuration ).
BeanFactory is a place for centralized application configuration management, which is extremely simple for application development, so that developers can concentrate on their businesses.
BeanFactory needs to manage the bean lifecycle. For example, the following interfaces must be implemented in order during initialization:
1. BeanNameAware's {@ code setBeanName}
2. BeanClassLoaderAware's {@ code setBeanClassLoader}
3. BeanFactoryAware's {@ code setBeanFactory}
4. ResourceLoaderAware's {@ code setResourceLoader} is only valid for application context
5. ApplicationEventPublisherAware's {@ code setApplicationEventPublisher} is only valid for application context
6. MessageSourceAware's {@ code setMessageSource} is only valid for application context
7. ApplicationContextAware's {@ code setApplicationContext} is only valid for application context
8. ServletContextAware's {@ code setServletContext} is only valid for application context
9. {@ code postProcessBeforeInitialization} methods of BeanPostProcessors
10. InitializingBean's {@ code afterPropertiesSet}
11. init-method configured in a custom init-method definition xml
12. {@ code postProcessAfterInitialization} methods of BeanPostProcessors
You can also disable the container interface:
1. DisposableBean's {@ code destroy}
2. a custom destroy-method definition destroy-method in xml configuration
The interface defines a variable String FACTORY_BEAN_PREFIX = "&";
This is used to identify whether FactoryBean is obtained or the createBean instance created by FactoryBean. If & starts, get FactoryBean; otherwise, get the instance created by createBean.
Let's take a look at the defined method:
A. Obtain the bean. The singleton and prototype can be implemented here.
Object getBean (String name) throws BeansException; you can use an alias to find it.
<T> T getBean (String name, Class <T> requiredType) throws BeansException;
<T> T getBean (Class <T> requiredType) throws BeansException; The type here can be an interface or a subclass, but cannot be null
Object getBean (String name, Object... args) throws BeansException;
B. Determine whether the bean is included. trap: no matter whether the class is an abstract class or not, if the class is lazy loaded or not within the container range, true is returned as long as it meets the condition. Therefore, true may not be able to get the instance from getBean.
Boolean containsBean (String name );
C, Singleton, prototype, bean type judgment
Boolean isSingleton (String name) throws NoSuchBeanDefinitionException;
Boolean isPrototype (String name) throws NoSuchBeanDefinitionException;
Boolean isTypeMatch (String name, Class <?> TargetType) throws NoSuchBeanDefinitionException;
D. Obtain the bean type and alias.
Class <?> GetType (String name) throws NoSuchBeanDefinitionException;
String [] getAliases (String name );
2. AutowireCapableBeanFactory
Manage existing instances based on BeanFactory.
You can use this interface to integrate other frameworks, bundle and populate existing instances that are not managed by Spring, such as Actions and Tapestry pages integrated with WebWork.
Generally, application developers do not use this interface, so the appearance implementation class like ApplicationContext does not implement this interface. If it is really itchy, it can be obtained through the getAutowireCapableBeanFactory interface of ApplicationContext.
Five Automatic Assembly policies are defined here: AUTOWIRE_NO is not injected, AUTOWIRE_BY_NAME is assembled using the bean name Policy, AUTOWIRE_BY_TYPE is used, AUTOWIRE_CONSTRUCTOR is used, and AUTOWIRE_AUTODETECT is the automatic assembly policy.
The automatic policy here is to try the constructor first, and then the byType. This should correspond to the Assembly policy in the xml configuration file.
Continue to view the defined api:
A. Typical method for creating and filling external bean instances
<T> T createBean (Class <T> beanClass) throws BeansException;
Void autowireBean (Object existingBean) throws BeansException; // use autowireBeanProperties to assemble attributes
Object configureBean (Object existingBean, String beanName) throws BeansException; // automatically assembles attributes, fills in attribute values, and fills attributes with factory callbacks such as setBeanName and setBeanFactory. It is best to call post processor
Object resolveDependency (DependencyDescriptor descriptor, String beanName) throws BeansException;
B. Special Methods for fine-grained control in bean Lifecycle
Object createBean (Class <?> BeanClass, int autowireMode, boolean dependencyCheck) throws BeansException; // The bean is fully initialized, including BeanPostProcessors and initializeBean.
Object autowire (Class <?> BeanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
Void autowireBeanProperties (Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException;
Void applyBeanPropertyValues (Object existingBean, String beanName) throws BeansException;
Object initializeBean (Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsBeforeInitialization (Object existingBean, String beanName) throws BeansException;
Object applyBeanPostProcessorsAfterInitialization (Object existingBean, String beanName) throws BeansException;
Object resolveDependency (DependencyDescriptor descriptor, String beanName, Set <String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
3. HierarchicalBeanFactory
The access function of the parent container is provided. For the settings of the parent container, you need to find setParentBeanFactory of ableablebeanfactory (the interface opened the settings and obtained them !).
There is not much to say here. go directly to the api:
A. Obtain the bean factory of the parent container.
BeanFactory getParentBeanFactory ();
B. Determine whether the current container protects the bean.
Boolean containsLocalBean (String name );
4. ListableBeanFactory
Spring encourages the use of Apis defined by this interface when obtaining beans. There is also a Beanfactory for ease of use. The other four interfaces are not encouraged.
The bean iteration function in the container is provided, and bean search is no longer required. for example, you can obtain all beans at a time (too violent) and retrieve beans by type. when you look at SpringMVC, the specific implementation policy under the scan package path is this method (the BeanFactoryUtils encapsulated api is used over there ).
If HierarchicalBeanFactory is implemented at the same time, the returned value does not consider the parent class BeanFactory, but only the class defined by the current factory. Of course, you can also use the BeanFactoryUtils helper class to find the class in the ancestor factory.
The method in this interface only considers the bean defined by this factory. these methods ignore the singlebean registered by registerSingleton of ableablebeanfactory (getBeanNamesOfType and getBeansOfType are exceptions, and manually registered Singleton is also considered ). of course, BeanFactory's getBean can transparently access these special beans. of course, in typical cases, all beans are defined by external beans, so applications do not need to worry about these differences.
Note: The implementation methods of getBeanDefinitionCount and containsBeanDefinition are better because they are less efficient and rarely used.
Continue with the api
A. Obtain attributes of all beans by brute force:
Boolean containsBeanDefinition (String beanName); // whether the bean is included
Int getBeanDefinitionCount (); // number of beans defined in the current factory
String [] getBeanDefinitionNames (); // obtain the name of all beans defined in the current factory
B. Obtain the bean Based on the bean type.
This method only checks the top-level bean. It does not check the nested bean. The bean created by FactoryBean will match the FactoryBean instead of the original type.
Similarly, the bean in the parent factory is not considered. You can use beanNamesForTypeIncludingAncestors in BeanFactoryUtils.
For other registration methods, this will be included in the judgment.
In this version, getBeanNamesForType will match all types of beans, including Singleton, prototype, and FactoryBean. The returned bean names will be sorted according to the backend configuration.
String [] getBeanNamesForType (Class <?> Type); // obtain the bean names (including subclass) of the given type, and judge by bean definition or getObjectType of FactoryBean.
String [] getBeanNamesForType (Class <?> Type, boolean includeNonSingletons, boolean allowEagerInit );
<T> Map <String, T> getBeansOfType (Class <T> type) throws BeansException; // if you want to protect the classes that are lazy to load, the class initialized by FactoryBean and the class initialized by the factory method will be initialized. that is to say, executing this method will execute the corresponding initialization.
<T> Map <String, T> getBeansOfType (Class <T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
C. Search for classes using annotations
Map <String, Object> getBeansWithAnnotation (Class <? Extends Annotation> annotationType) throws BeansException;
D. Search for the Annotation on a class. If the annotation cannot be found, the parent class and interface annotation are also used.
<A extends Annotation> A findAnnotationOnBean (String beanName, Class <A> annotationType );
5. ConfigurableBeanFactory
Define BeanFactory configuration.
Too many APIs are defined here, such as the class loader, type conversion, Attribute Editor, BeanPostProcessor, scope, bean definition, processing bean dependencies, merging other ConfigurableBeanFactory, and how to destroy beans.
Two scopes are defined: singleton and prototype. You can add them through registerScope.
SCOPE_SINGLETON, SCOPE_PROTOTYPE
Many APIs are defined here, so we only talk about the business here. For specific APIs, refer to the appendix at the end of this article:
A. parent container settings. Once set, modifications are not allowed.
B. Set and obtain the Class Loader. The class loader in the current thread is used by default.
C. Create a temporary class loader for type Matching. Fortunately, it is usually null and the standard loader defined above is used.
D. Whether to cache bean metadata, such as bean difinition and parsed classes. cache is enabled by default.
E. Define the expression parser used to parse bean definition.
F, type converter
G, Attribute Editor
H, BeanFactory is a custom converter used to convert bean property values or parameter values.
I, string value Parser (think of ArgumentResolver in mvc)
J. Big boss BeanPostProcessor is used to enhance bean initialization.
K. scope definition
L. access permission Control
M. merge other ConfigurableBeanFactory configurations, including the BeanPostProcessor and scope mentioned above.
N, bean definition Processing
O. bean creation Status control, which is used when circular dependency is resolved
P. Handle bean Dependencies
Q: bean lifecycle management-destroy bean
6. ConfigableListableBeanFactory
Provides bean definition parsing and registration functions, and then pre-loads the singleton (to solve the problem of circular dependency ).
It seems that the general development will directly define such an interface, instead of dividing so much according to usage as Spring, and then merging it here.
A. Set the ignored dependency and register the special dependency found.
Void ignoreDependencyType (Class <?> Type); // ignore type
Void ignoreDependencyInterface (Class <?> Ifc); // ignore the interface
Void registerResolvableDependency (Class <?> DependencyType, Object autowiredValue );
Boolean isAutowireCandidate (String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException;
B. Obtain the bean definition (you can access the attribute value and the parameter value of the constructor)
BeanDefinition getBeanDefinition (String beanName) throws NoSuchBeanDefinitionException;
C. Lock the configuration information. It will be used when refresh is called.
Void freezeConfiguration ();
Boolean isConfigurationFrozen ();
D. Pre-loading is not a single example of lazy loading. It is used to solve the circular dependency problem.
Void preInstantiateSingletons () throws BeansException;
Appendix -- the api defined in ConfigureableBeanFactory:
A. parent container settings. Once set, modifications are not allowed.
Void setParentBeanFactory (BeanFactory parentBeanFactory) throws IllegalStateException;
B. Set and obtain the Class Loader. The class loader in the current thread is used by default.
Void setBeanClassLoader (ClassLoader beanClassLoader );
ClassLoader getBeanClassLoader ();
C. Create a temporary class loader for type Matching. Fortunately, it is usually null and the standard loader defined above is used.
Void setTempClassLoader (ClassLoader tempClassLoader );
ClassLoader getTempClassLoader ();
D. Whether to cache bean metadata, such as bean difinition and parsed classes. cache is enabled by default.
Void setCacheBeanMetadata (boolean cacheBeanMetadata );
Boolean isCacheBeanMetadata ();
E. Define the expression parser used to parse bean definition.
Void setBeanExpressionResolver (BeanExpressionResolver resolver );
BeanExpressionResolver getBeanExpressionResolver ();
F, type converter
Void setConversionService (ConversionService conversionService );
ConversionService getConversionService ();
G, Attribute Editor
Void addPropertyEditorRegistrar (PropertyEditorRegistrar registrar );
Void registerCustomEditor (Class <?> RequiredType, Class <? Extends PropertyEditor> propertyEditorClass );
Void copyRegisteredEditorsTo (PropertyEditorRegistry registry );
H, BeanFactory is a custom converter used to convert bean property values or parameter values.
Void setTypeConverter (TypeConverter typeConverter );
TypeConverter getTypeConverter ();
I, string value Parser (think of ArgumentResolver in mvc)
Void addEmbeddedValueResolver (StringValueResolver valueResolver );
String resolveEmbeddedValue (String value );
J. Big boss BeanPostProcessor is used to enhance bean initialization.
Void addBeanPostProcessor (BeanPostProcessor beanPostProcessor );
Int getBeanPostProcessorCount ();
K. scope definition
Void registerScope (String scopeName, Scope scope );
String [] getRegisteredScopeNames ();
Scope getRegisteredScope (String scopeName );
L. access permission Control
AccessControlContext getAccessControlContext ();
M. merge other ConfigurableBeanFactory configurations, including the BeanPostProcessor and scope mentioned above.
Void copyConfigurationFrom (ConfigurableBeanFactory otherFactory );
N, bean definition Processing
Void registerAlias (String beanName, String alias) throws BeanDefinitionStoreException; // register an alias
Void resolveAliases (StringValueResolver valueResolver );
BeanDefinition getMergedBeanDefinition (String beanName) throws NoSuchBeanDefinitionException; // merge bean definitions, including the parent container's
Boolean isFactoryBean (String name) throws NoSuchBeanDefinitionException; // whether it is of the FactoryBean type
O. bean creation Status control, which is used when circular dependency is resolved
Void setCurrentlyInCreation (String beanName, boolean inCreation );
Boolean isCurrentlyInCreation (String beanName );
P. Handle bean Dependencies
Void registerDependentBean (String beanName, String dependentBeanName );
String [] getDependentBeans (String beanName );
String [] getDependenciesForBean (String beanName );
Q: bean lifecycle management-destroy bean
Void destroyBean (String beanName, Object beanInstance );
Void destroyScopedBean (String beanName );
Void destroySingletons ();