In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/03 Report--
WeChat account: GitShare
Official account of Wechat: a straw that loves to toss.
If you have any questions or suggestions, please leave a message on the official account [1]
Previous continuation
In order to help the majority of SpringBoot users to "know what it is, but also need to know why", the author will deeply analyze the SpringBoot2.0.0.RELEASE version through a series of SpringBoot articles, so that you can have a deep understanding of its internal working principle.
1. [SpringBoot] use SpringBoot to quickly build and start the project
2. [SpringBoot] explain the startup process of SpringBoot application in detail
3. [SpringBoot] in-depth analysis of the application type identification mechanism of SpringBoot
Java SPI mechanism
What is Java SPI?
The full name of SPI is Service Provider Interface. Most developers may not be familiar with it because this is for vendors or plug-ins.
There are often many different implementation schemes for the abstract modules in our system, such as the scheme of log module, xml parsing module, jdbc module and so on.
In the object-oriented design, we generally recommend the interface-based programming between modules, and the implementation classes are not hard-coded between modules. Once a specific implementation class is involved in the code, it violates the principle of pluggability
If you need to replace an implementation, you need to modify the code. In order to realize that it can not be dynamically specified in the program when the module is assembled, a service discovery mechanism is needed.
Java SPI provides such a mechanism: a mechanism to find an implementation for an interface.
Java SPI's agreement
When the service provider provides an implementation of the service interface, a file named after the service interface is also created in the META-INF/services/ directory of the jar package.
In this file is the specific implementation class that implements the service interface. When the external program assembles this module, it can find the specific implementation class name through the configuration file in the jar package META-INF/services/, and load the instantiation to complete the injection of the module.
Based on such a convention, it is good to find the implementation class of the service interface without having to make it in the code.
Jdk provides a utility class for service implementation lookups: java.util.ServiceLoader.
SPI Mechanism in SpringBoot
There is also a loading mechanism similar to Java SPI in Spring. It configures the implementation class names of the interfaces in the META-INF/spring.factories file, then reads these configuration files in the program and instantiates them.
This custom SPI mechanism is the basis of the Spring Boot Starter implementation.
Principle of Spring Factories implementation
The SpringFactoriesLoader class is defined in the spring-core package, which implements the function of retrieving the META-INF/spring.factories file and getting the configuration of the specified interface.
Two external methods are defined in this class:
1 、 loadFactories
Get an instance of its implementation class based on the interface class, and this method returns a list of objects with its source code:
Public static List loadFactories (Class factoryClass, @ Nullable ClassLoader classLoader) {
Assert.notNull (factoryClass, "'factoryClass' must not be null")
ClassLoader classLoaderToUse = classLoader
If (classLoaderToUse = = null) {
ClassLoaderToUse = SpringFactoriesLoader.class.getClassLoader ()
}
List factoryNames = loadFactoryNames (factoryClass, classLoaderToUse)
If (logger.isTraceEnabled ()) {
Logger.trace ("Loaded [" + factoryClass.getName () + "] names:" + factoryNames)
}
List result = new ArrayList (factoryNames.size ())
For (String factoryName: factoryNames) {
Result.add (instantiateFactory (factoryName, factoryClass, classLoaderToUse))
}
AnnotationAwareOrderComparator.sort (result)
Return result
}
Get ClassLoader first
Call the loadFacotoryNames () method to get the factoryNames. The source code is as follows:
Public static List loadFactoryNames (Class factoryClass, @ Nullable ClassLoader classLoader) {
/ / get the class name
String factoryClassName = factoryClass.getName ()
/ / get the value of the specified factory in the Map of the configuration information of all META-INF/spring.factories files under the current ClassLoader. If it does not exist, an empty list is returned.
Return loadSpringFactories (classLoader) .getOrDefault (factoryClassName, Collections.emptyList ())
}
Call the loadSpringFactories method to get the configuration information of all META-INF/spring.factories files under the current ClassLoader
Private static Map loadSpringFactories (@ Nullable ClassLoader classLoader) {
/ / get the corresponding from the cache
MultiValueMap result = cache.get (classLoader)
If (result! = null)
Return result
Try {
/ / get all the URL paths that contain META-INF/spring.factories files under the current ClassLoader
Enumeration urls = (classLoader! = null?
ClassLoader.getResources (FACTORIES_RESOURCE_LOCATION):
ClassLoader.getSystemResources (FACTORIES_RESOURCE_LOCATION))
/ / initial return object
Result = new LinkedMultiValueMap ()
/ / iterate through all URL collections containing META-INF/spring.factories files
While (urls.hasMoreElements ()) {
URL url = urls.nextElement ()
UrlResource resource = new UrlResource (url)
/ / convert to Properties object
Properties properties = PropertiesLoaderUtils.loadProperties (resource)
/ / iterate through all the attributes in the META-INF/spring.factories file
For (Map.Entry entry: properties.entrySet ()) {
/ / if an API wants to configure multiple implementation classes, you can split it with','to convert the value corresponding to the current Key to List
List factoryClassNames = Arrays.asList (StringUtils.commaDelimitedListToStringArray ((String) entry.getValue ()
/ / add to the returned object
Result.addAll ((String) entry.getKey (), factoryClassNames)
}
}
/ / add to the cache
Cache.put (classLoader, result)
/ / return the result
Return result
}
Catch (IOException ex) {
Throw new IllegalArgumentException ("Unable to load factories from location [" +)
FACTORIES_RESOURCE_LOCATION + "]", ex)
}
}
We can configure the spring.factories file in our own jar without affecting the configuration elsewhere or being overwritten by someone else's configuration.
This is very helpful for us to customize the extension later.
Call instantiateFactory to instantiate the corresponding Factory object obtained, and its source code:
Private static T instantiateFactory (String instanceClassName, Class factoryClass, ClassLoader classLoader) {
Try {
/ / get an instance of the class based on the class name, which was parsed in the previous article.
Class instanceClass = ClassUtils.forName (instanceClassName, classLoader)
/ / isAssignableFrom () determines whether the object of instanceClassName is a subclass of FactoryClass or the same class, and returns true if so.
If (! factoryClass.isAssignableFrom (instanceClass)) {
/ / throw an exception if the instantiated target class is not a subclass of the Factory class or is not a Factory class
Throw new IllegalArgumentException ("Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName () + "]")
}
/ / instantiate the target class through the java reflection mechanism
Return (T) ReflectionUtils.accessibleConstructor (instanceClass). NewInstance ()
}
Catch (Throwable ex) {
Throw new IllegalArgumentException ("Unable to instantiate factory class:" + factoryClass.getName (), ex)
}
}
We can see from this code that it only supports constructors with no parameters.
2 、 loadFactoryNames
To get the name of its interface class based on the interface, this method returns a list of class names, whose source code has been analyzed above.
Application of SpringBoot when starting up
During SpringBoot startup, the SpringApplication object is created with the following two lines of code:
SetInitializers ((Collection) getSpringFactoriesInstances (ApplicationContextInitializer.class))
SetListeners ((Collection) getSpringFactoriesInstances (ApplicationListener.class))
Use SpringFactoriesLoader to find and load all available ApplicationContextInitializer in the application's classpath
Use SpringFactoriesLoader to find and load all available ApplicationListener in the application's classpath
Application of Spring Factories Mechanism
In our daily work, we may need to implement some SDK or Spring Boot Starter to be used by others, and with this we can use the Factories mechanism.
The Factories mechanism allows the use of SDK or Starter to require little or no configuration, just to introduce our jar package into the service.
Knowledge point
IsAssignableFrom () parsing of Class
Public native boolean isAssignableFrom (Class cls)
It can be seen from the method signature that it is written by a local method, that is, C code.
Its function is:
There are two classes of type Class, one is the class object that calls the isAssignableFrom method (later called object a), and the class object in the method as a parameter (called object b). These two objects return true if the following conditions are met, otherwise false:
The class information corresponding to an object is the parent class or interface of the class information corresponding to b object. It is simply understood that an is the parent class or interface of b
The class information corresponding to an object is the same as that corresponding to b object. It is simply understood that an and b are the same class or the same interface.
Postscript
In order to help the majority of SpringBoot users to "know what it is, but also need to know why", the author will deeply analyze the SpringBoot2.0.0.RELEASE version through a series of SpringBoot articles, so that you can have a deep understanding of its internal working principle. Please follow the official account of GitShare to provide you with more and more high-quality technical tutorials.
Picture note: love to toss about the straw
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.