Needs and problems
Core demands
-
Existing system, no reconstruction
-
Spring version 3.x, do not plan to upgrade or introduce Spring Boot
-
It is expected to realize some functional enhancements on the premise of less code changes
For example, make a unified log for the whole site, add the summary of web calls of rpg framework and the summary information of database access layer for them
Problems faced -
Spring of 3.x has no conditional annotation, which leads to not knowing when to configure these things and when not to configure them
-
Unable to automatically locate the auto configuration that needs to be loaded, we need other means to enable spring to load into the customized functions we put in
Core solutions
Conditional judgement
- Judge through BeanFactoryPostProcessor
It is an extension point provided by spring. After the definition of BeanFactory and before bean initialization, it can do some post-processing on my bean definition. At this time, it can make a judgment on my bean definition to see which bean definitions exist and which bean definitions I lack. At this time, I can also add a bean definition and add some self-defined ones Bean of righteousness
Configuration loading - Writin g Java Con class
- Introduce configuration class
• put the written Java Con fi g class into component scan, and let the component scan of the current system contain my Con fi g
• load my file on the path of loading through XML file, or import my file manually
Two extension points of Spring
BeanPostProcessor
- For Bean instances
- Provide custom logical callback after Bean creation
After bean initialization, some processing can be done in the bean instance, and a post enhancement can be done to provide some logic
BeanFactoryPostProcessor - Defined for Bean
- Get configuration metadata before creating a Bean
- static method needs to be defined in Java Con g (important)
Some customization of Bean
Lifecycle Callback (lifecycle)
- InitializingBean (implement this interface) / @ PostConstruct (annotation Implementation) / init method (attribute of xml file or specified in bean annotation)
About initialization, after the bean is created, make a customization to call a specific method after it is created successfully - DisposableBean / @PreDestroy / destroy-method
DisposableBean: implement this interface. When destroying, my spring will call the corresponding method
@PreDestroy: the annotated method will make a call when the bean is destroyed
Destroy method: in xml, configure the method called when the bean is destroyed
XxxAware interface - ApplicationContextAware
This ApplicationContext can be injected through the interface - BeanFactoryAware
You can inject this BeanFactory through the interface - BeanNameAware
You can inject the bean name through the interface
Some common operations
Judge whether a class exists
-
ClassUtils.isPresent()
Determine whether a class exists in classpath
Determine whether a Bean is defined -
ListableBeanFactory.containsBeanDefinition()
Determine whether a Bean is defined -
ListableBeanFactory.getBeanNamesForType()
Through this method, some specific types of beans and which bean names have been defined
Register Bean definition -
BeanDefinitionRegistry.registerBeanDefinition()
• GenericBeanDefinition
Through this method, make a bean definition -
BeanFactory.registerSingleton()
Define a bean definition
Example
The contents are as follows:
Modification of pom file
Code:
@Configuration public class GreetingAutoConfiguration { @Bean public static GreetingBeanFactoryPostProcessor greetingBeanFactoryPostProcessor() {//BeanFactoryPostProcessor is static return new GreetingBeanFactoryPostProcessor(); } }
@Slf4j public class GreetingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {//After bean initialization, BeanPostProcessor does some processing in the bean instance, and can do a post enhancement to provide some logic public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { boolean hasClass = ClassUtils.isPresent("geektime.spring.hello.greeting.GreetingApplicationRunner", GreetingBeanFactoryPostProcessor.class.getClassLoader());//Determine whether this class exists in classpath if (!hasClass) { log.info("GreetingApplicationRunner is NOT present in CLASSPATH.");//If no output log exists return; } if (beanFactory.containsBeanDefinition("greetingApplicationRunner")) {//If so, judge whether the greeting application runner has been defined log.info("We already have a greetingApplicationRunner bean registered."); return; } register(beanFactory);//If it doesn't exist, we will create it ourselves to make a registration } private void register(ConfigurableListableBeanFactory beanFactory) { if (beanFactory instanceof BeanDefinitionRegistry) {//If the incoming beanFactory is an instance of BeanDefinitionRegistry type, you can use the registerBeanDefinition method GenericBeanDefinition beanDefinition = new GenericBeanDefinition();//Through this method, make a bean definition and set its class beanDefinition.setBeanClass(GreetingApplicationRunner.class); ((BeanDefinitionRegistry) beanFactory) .registerBeanDefinition("greetingApplicationRunner", beanDefinition);//Define the name of a bean, that is, define a bean through beanDefinition, and assign a name to it through registerBeanDefinition } else { beanFactory.registerSingleton("greetingApplicationRunner", new GreetingApplicationRunner());//If it is not this class, use registerSingleton to register } } }
Result
Automatic configuration
Manual configuration