Help me to the Internet cafe 2022-05-14 14:40:00 阅读数:769
Last article Spring Ioc Source analysis series --Ioc Source code entry analysis Already introduced Ioc The inlet of the container refresh()
Method , And analyzed refresh()
The first three sub methods in the method are analyzed . Remember what you analyzed ? I guess I forgot what I analyzed , It can be said that I saw a lonely . But don't panic , It must be normal to read and forget , Need to review , You'd better take some notes , Only when you have your own precipitation will you be impressed . You'd better follow the code and debug it yourself several times , It's on paper , We must know that we must do it .
Okay , Here's a review of the last article . The last article mainly analyzed three methods ,prepareRefresh()
Set some properties before starting the container ,obtainFreshBeanFactory()
Method completes reading the configuration file , The implementation of this method will be aimed at xml Configure and create internal containers , This container is responsible for bean Creation and management of , Will be carried out in BeanDefinition
Registration of ,prepareBeanFactory(beanFactory)
This method mainly registers some systems that need to be used in the container bean
, for example classloader
,BeanFactoryPostProcessor
etc. .
After drinking chicken soup and looking back , The following is the beginning of the main body of today's article .
Think about a problem ,Spring Provides very good scalability , So where is scalability reflected ? Different people have different opinions on this issue , But compress the scene , Compressed to the previous article, we have obtained a loading completion BeanDefinition
On the container , I'm in a unified BeanDefinition
After loading , I want to modify one or add one BeanDefinition
, How to achieve it at this time ?
Yes Spring Familiar readers may have guessed , It can be used at this time BeanFactoryPostProcessor
The post processor completes this operation , Then this article will solve two questions :
The first question will be illustrated by an example , The second question will be explained through source code analysis . Don't talk nonsense , to BeanFactoryPostProcessor
Introduce , Then use the example of the previous article to realize BeanFactoryPostProcessor
To replace UserService
The implementation of the .
This is a container hook method , Allows you to customize and modify the context of your application bean
Definition , Adjust the context bean
Factory bean
Property value . For users who want to overwrite the configuration in the application context with the custom configuration file of the system administrator bean
Properties are very effective .BeanFactoryPostProcessor
It can be done with bean
Define interactions and modifications , But not with bean
Instance interaction . Doing so may lead to premature bean
Instantiation , Violate the container and cause unexpected side effects . if necessary bean Instance interaction , Please consider implementing BeanPostProcessor
.ApplicationContext
Automatically detect its bean
In the definition BeanFactoryPostProcessor
, And create any other bean
Apply them before . BeanFactoryPostProcessor
You can also register to... Programmatically ConfigurableApplicationContext
.
This class has only one method , The input parameter is the current container , So let's see postProcessBeanFactory()
This method .
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
*
* Modify the internal of the application context after standard initialization bean factory .
* all bean Definitions will be loaded , But not yet. bean Be instantiated .
* This allows you to override or add attributes , Even eager to initialize bean.
*
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
You can see that the operation space here is very large , Directly transfer the current container into , It means that you can do anything based on the current container . For example, you look at the goddess every day , It's impossible to be expected , But one day through a portal , Sent the goddess to your house , Can you do whatever you want , Do whatever you want , For example, you can let her wear the clothes you like , Eat what you like and so on .
Then let's implement it with code . In the last article Spring Ioc Source analysis series --Ioc Source code entry analysis Add code based on , All source code can be found in My warehouse ioc-sourcecode-analysis-code-demo Found in .
First, create a new one ReplaceUserServiceImpl
Class implementation UserService
.
/**
* @author Codegitz
* @date 2022/5/12 15:57
**/
public class ReplaceUserServiceImpl implements UserService {
@Override
public User getUser(String name, String age) {
User user = new User();
user.setId("1");
// The assignment is changed here
user.setName("ReplaceUser-" + name);
user.setAge(age);
return user;
}
}
Then use a class to implement BeanFactoryPostProcessor
. You can see that my logic here is also very simple , Is to judge whether there is a named userService
Of BeanDefinition
, If so, replace its implementation with io.codegitz.service.impl.ReplaceUserServiceImpl
.
/**
* @author Codegitz
* @date 2022/5/12 16:01
**/
public class ReplaceUserBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (beanFactory.containsBeanDefinition("userService")){
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
beanDefinition.setBeanClassName("io.codegitz.service.impl.ReplaceUserServiceImpl");
}
}
}
The post processor is ready , Next, register the post processor in the container , My code example uses xml
The way .
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="io.codegitz.service.impl.UserServiceImpl"/>
<!-- Register the post processor -->
<bean id="processor" class="io.codegitz.processor.ReplaceUserBeanFactoryPostProcessor"/>
</beans>
It's all done here , Then you can start the boot class to run and see the effect . You can see that the implementation here has been replaced by ReplaceUserServiceImpl
, Explain our ReplaceUserBeanFactoryPostProcessor
The post processor is working , So how did it take effect ? Enter the source code analysis in the next section .
The above function has been realized through an example , So how is it implemented in the source code ? Here will be connected with the source code analysis of the previous article , Continue to refresh()
Wandering in the method . The previous article has analyzed the first three , This article will continue to analyze two methods , Namely postProcessBeanFactory(beanFactory)
and invokeBeanFactoryPostProcessors(beanFactory)
,invokeBeanFactoryPostProcessors(beanFactory)
Is the logic of the post processor , Link up the above example . good heavens , Connect with each other .
This is an empty method , It's left for subclasses to implement , Mainly a few web
dependent ApplicationContext
Will rewrite this method , The current container is passed in , The operating space is also very large . Because it's an empty method , No more details here .
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for registering special
* BeanPostProcessors etc in certain ApplicationContext implementations.
*
* Modify the internal of the application context after standard initialization bean factory .
* all bean The definitions have been loaded , But not yet. bean Be instantiated .
* This allows for some ApplicationContext Register special in the implementation BeanPostProcessors etc. .
*
* @param beanFactory the bean factory used by the application context
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
Then we enter today's play , Follow up the code , You can see that the main code implementation is delegated to PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
To achieve .
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*
* Instantiate and call all registered BeanFactoryPostProcessor bean, If the order is given , Then execute in order
* All post processors must be in other singletons bean Called before instantiation
*/
// Instantiate and call all BeanFactoryPostProcessor beans
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// This method performs two operations
// 1. Put the given BeanFactoryPostProcessor Incoming execution
// 2. Automatically scan all the... In the container BeanFactoryPostProcessor perform
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
// Detect whether there is temporary for type matching ClassLoader and LoadTimeWeaver
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
To follow up PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
Code inside . This method is longer , But the logic is very simple , Follow the notes. It's not a big problem to understand .
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// The conventional BeanFactoryPostProcessor Post Processors
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// Extended registration BeanDefinition Of BeanDefinitionRegistryPostProcessor Post Processors
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// Put it into different post processor lists according to the type
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// There is no initialization here FactoryBeans, Because if you initialize first BeanFactoryPostProcessor You can't do the initialization for bean It works
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// First, we will call the implementation PriorityOrdered Interface BeanDefinitionRegistryPostProcessors
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// Next, the call implements Ordered Interface BeanDefinitionRegistryPostProcessors
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// Last , Call... That does not implement the above interface BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
// Why should we put... Here again reiterate Set to true?
// Because here BeanDefinitionRegistryPostProcessor May register another BeanFactoryPostProcessor,
// So you need a loop to iterate , Until now, there is no... In the container BeanFactoryPostProcessor until
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// Registration may continue here BeanFactoryPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// The previous processing has completed all BeanDefinitionRegistryPostProcessor,
// The next two methods are to deal with BeanFactoryPostProcessor,
// Note that this only deals with the method passed in beanFactoryPostProcessors ,
// After processing this, the subsequent logic will automatically detect all... In the current container BeanFactoryPostProcessor, Then call... One by one
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
// If given beanFactory No BeanDefinitionRegistry,
// Then you don't need to make the previous call BeanDefinitionRegistryPostProcessor The operation of ,
// Directly call the given beanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// The logic here is the same as that above BeanDefinitionRegistryPostProcessor The processing logic is similar
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// Classify according to different priorities BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// If the first stage has been handled , No longer handle
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// First of all, the implementation is called PriorityOrdered Interface BeanFactoryPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// Secondly, the call implements Ordered Interface BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// Finally, call the... That does not implement the above interface BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// Clear cached merged bean definitions Definition , Because the postprocessor may have modified the original metadata , For example, replace a placeholder in a value ...
beanFactory.clearMetadataCache();
}
This method mainly does the following things :
BeanDefinitionRegistry
type , If it is , Then judge A given beanFactoryPostProcessors
Whether there is BeanDefinitionRegistryPostProcessor
Type of postprocessor , If so, execute postProcessBeanDefinitionRegistry()
Method , Conduct BeanDefinition
Registration of . Then, we will get the implementation of... In the current container respectively PriorityOrdered
、Ordered
Interface and those that do not implement the sorting interface BeanDefinitionRegistryPostProcessor
, After sorting, execute .BeanDefinitionRegistry
type , Call directly invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory)
Method calls all the given BeanFactoryPostProcessor
.beanFactoryPostProcessors
, Here we will detect the existing in the execution container BeanFactoryPostProcessor
. Here will also follow PriorityOrdered
and Ordered
Interface and the order in which the sorting interface is not implemented .The logic of this method is relatively simple , That is, the amount of code is relatively large , It takes patience to read .
Next, let's look at the contents of some word methods
sortPostProcessors() Finish post processor sorting
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
// Relatively simple , Is to get a comparator Comparator , as for Comparator Principle , You can read the relevant articles by yourself
Comparator<Object> comparatorToUse = null;
if (beanFactory instanceof DefaultListableBeanFactory) {
comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
}
if (comparatorToUse == null) {
comparatorToUse = OrderComparator.INSTANCE;
}
// Sort
postProcessors.sort(comparatorToUse);
}
invokeBeanDefinitionRegistryPostProcessors() Call all BeanDefinitionRegistryPostProcessor
This method is also relatively simple , Is to call one by one BeanDefinitionRegistryPostProcessor
Post Processors .
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
* Call the given BeanDefinitionRegistryPostProcessor bean.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
invokeBeanFactoryPostProcessors() Call all BeanFactoryPostProcessor
Call one by one BeanFactoryPostProcessor
Post Processors .
/**
* Invoke the given BeanFactoryPostProcessor beans.
* Call the given BeanFactoryPostProcessor bean.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
beanFactory.getBeanNamesForType() Get... By type bean name
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)
It will get all the information of this type according to the type passed in bean name .
Follow up code view , Would call doGetBeanNamesForType()
Method to get .
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
// The configuration is not frozen || The type is empty || Early initialization is not allowed entering
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
// Allow early initialization
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
To follow up doGetBeanNamesForType()
Method , This method is also relatively long , But the logic is also relatively clear , Just traverse beanDefinitionNames
Judge whether it meets the type requirements , If yes, return .
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();
// Check all bean definitions.
// From all of beanDefinitionNames Check all that meet the type requirements bean , Join in result
for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
// If bean Name is not defined as other bean Another name for , Then bean Meet the requirements .
if (!isAlias(beanName)) {
try {
// obtain beanName Of RootBeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
boolean isFactoryBean = isFactoryBean(beanName, mbd);
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
// Whether the type matches
boolean matchFound = false;
boolean allowFactoryBeanInit = allowEagerInit || containsSingleton(beanName);
boolean isNonLazyDecorated = dbd != null && !mbd.isLazyInit();
// The main thing is to call isTypeMatch() Method to determine whether the types match
if (!isFactoryBean) {
if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
else {
if (includeNonSingletons || isNonLazyDecorated ||
(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
if (!matchFound) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
}
}
// If it matches, add
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
// Omit some exception handling ..
}
}
}
// Check manually registered singletons too.
// Check the manually registered singleton bean
for (String beanName : this.manualSingletonNames) {
try {
// In case of FactoryBean, match object created by FactoryBean.
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
// Match found for this bean: do not match FactoryBean itself anymore.
continue;
}
// In case of FactoryBean, try to match FactoryBean itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
// Match raw bean instance (might be raw FactoryBean).
// If it matches, add
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Omit some exceptions ...
}
}
return StringUtils.toStringArray(result);
}
Come here BeanFactoryPostProcessor
The source code call and related logic analysis are finished , Is it simpler .
This article mainly introduces BeanFactoryPostProcessor
Use of post processor and underlying principle . The beginning of the article first reviews the content of the previous article , Then example driven analysis , First, a simple example is used to realize BeanFactoryPostProcessor
Use , Then the source code is analyzed , The idea of the whole article is relatively clear . So see here , Have you solved the first two questions of the article ?
版权声明:本文为[Help me to the Internet cafe]所创,转载请带上原文链接,感谢。 https://javamana.com/2022/134/202205141436333128.html