In this article, we will focus on the functions of classes that are often seen in Spring source code. There will be some code explanations in the middle, and the specific source code for each module will be written in a later article
BeanDefinition
The BeanDefinition holds information about our Bean. XML configuration 2.@Bean 3.@Component Spring generates BeanDefinition like object storage class information for spring production beans to use after reading bean configuration information. We can also generate a bean directly using beanDefinition.
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
// Get the beanDefinition object
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// Write the bean that needs to be produced
beanDefinition.setBeanClass(People.class);
// Register with the Spring container
applicationContext.registerBeanDefinition("myBean",beanDefinition);
// Refresh the container
applicationContext.refresh();
/ / get a bean
System.out.println(applicationContext.getBean(People.class));
System.out.println(applicationContext.getBean("myBean"));
}
/ / the result
//spring.bean.People@1ce92674
//spring.bean.People@1ce92674
Copy the code
BeanDefinitionReader
As the name implies, this class reads the class configuration. It has many implementation classes, such as XmlBeanDefinitionReader, which reads mode configurations
XmlBeanDefinitionReader
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
<bean id="people" class="spring.bean.People"/>
</beans>
Copy the code
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
/ / create beanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
// Loading beans into applicationContext from an XML file returns the number of beans read
int i = beanDefinitionReader.loadBeanDefinitions("applicationContext.xml");
System.out.println(i);
}
/ / the result
/ / 1
Copy the code
AnnotatedBeanDefinitionReader
Note that this class does not parse classes decorated with @beans,@Component annotations, etc. Instead, it parses the configuration of classes that need to be loaded, such as @scope, @lazy
@Scope("prototype")
public class People {}Copy the code
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
/ / create beanDefinitionReader
AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);
// Loading beans into applicationContext from an XML file returns the number of beans read
beanDefinitionReader.registerBean(People.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean("people"));
System.out.println(applicationContext.getBean("people"));
}
/ / the result
// spring.bean.People@5ae50ce6
// spring.bean.People@6f96c77
Copy the code
* people. class sets its scope to prototype. It can be seen from the result that the two People objects are really different
ClassPathBeanDefinitionScanner
Parsing @Component with package scan annotations (@bean annotations don’t bei scan)
package spring.bean;
import org.springframework.stereotype.Component;
@Component
public class People {}Copy the code
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(applicationContext);
classPathBeanDefinitionScanner.scan("spring.bean");
applicationContext.refresh();
System.out.println(applicationContext.getBean(People.class));
}
/ / the result
// spring.bean.People@74fe5c40
Copy the code
BeanFactory
There are many kinds of the BeanFactory in the Spring, in this paper, it is the core of the implementation class DefaultListableBeanFactory explanation DefaultListableBeanFactory realized many interface has many functions
- AliasRegistry: Supports aliases. One name can correspond to multiple aliases
- BeanDefinitionRegistry: You can register, save, remove, or retrieve a BeanDefinition
- BeanFactory: You can get bean objects based on their name, type, and alias
- SingletonBeanRegistry: Singleton beans can be registered and obtained directly
- SimpleAliasRegistry: It is a class that implements the functionality defined in the AliasRegistry interface and supports alias functionality
- ListableBeanFactory: To get the beanNames of all BeanDefinitions, you can get the beanNames of a type, you can get the beanNames of a type, you can get the beanNames of a type {type: Mapping of the corresponding Bean}
- HierarchicalBeanFactory: Adds the ability to get the parent BeanFactory to the BeanFactory
- DefaultSingletonBeanRegistry: it is a class, has realized the SingletonBeanRegistry interface, has the direct registration, obtain a singleton Bean function
- ConfigurableBeanFactory: HierarchicalBeanFactory and SingletonBeanRegistry, Added setting the parent BeanFactory, class loader (which means you can specify a class loader to load classes), and setting Spring An EL expression parser (indicating that the BeanFactory can parse EL expressions), a type conversion service (indicating that the BeanFactory can do type conversion), a BeanPostProcessor (indicating that the BeanFactory supports a Bean’s post-processor), You can merge BeanDefinitions, you can destroy a Bean, and so on
- The function of FactoryBeanRegistrySupport: support the FactoryBean
- AutowireCapableBeanFactory: is it inherited the BeanFactory directly, on the basis of the BeanFactory, support in the process of creating Bean that can be carried out on the Bean automatic assembly
- AbstractBeanFactory: Implements the ConfigurableBeanFactory interface, inherited FactoryBeanRegistrySupport, the function of the BeanFactory already very full, but not available automatic assembling and beanNames
- ConfigurableListableBeanFactory: inherited ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory
- AbstractAutowireCapableBeanFactory: inherited AbstractBeanFactory, realized AutowireCapableBeanFactory, has the function of automatic assembly
- DefaultListableBeanFactory: Inherited AbstractAutowireCapableBeanFactory, realized ConfigurableListableBeanFactory interface and BeanDefinitionRegistry interface, So DefaultListableBeanFactory function is very powerful
Through the above analysis, we can know that we can do many things by DefaultListableBeanFactory
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(People.class);
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
/ / register BeanDefinition
beanFactory.registerBeanDefinition("people", beanDefinition);
// Register an alias
beanFactory.registerAlias("people"."people1");
/ / register BeanPostProcessor
beanFactory.addBeanPostProcessor(new LubanBeanPostProcessor());
// Get the Bean object
System.out.println(beanFactory.getBean("people1"));
// Get beanNames by type
System.out.println(beanFactory.getBeanNamesForType(People.class));
Copy the code
ApplicationContext
ApplicationContext is an interface that can be thought of as a special BeanFactory
- HierarchicalBeanFactory: Has the ability to get the parent BeanFactory
- ListableBeanFactory: Has the ability to get beanNames
- ResourcePatternResolver: a resource loader that can fetch multiple resources (file resources, etc.) at once
- EnvironmentCapable: Runtime environment can be obtained (runtime environment functionality is not set)
- ApplicationEventPublisher: has the function of the broadcast events (without adding the function of the event listener)
- MessageSource: Has internationalization capabilities
Here are two of the more important implementation classes
AnnotationConfigApplicationContext
- ConfigurableApplicationContext: Inherited the ApplicationContext interface, increased, add event listener, add spring BeanFactoryPostProcessor, set up the Environment, to obtain ConfigurableListableBeanFactory etc. Function.
- AbstractApplicationContext: ConfigurableApplicationContext interface is realized
- GenericApplicationContext: Inherited AbstractApplicationContext, realized BeanDefinitionRegistry interface, has the function of all ApplicationContext, and can be registered BeanDefinition, Note that this class has an attribute (DefaultListableBeanFactory the beanFactory)
- AnnotationConfigRegistry: You can individually register a class as BeanDefinition (processing @Configuration annotations on that class, processing @Bean annotations) and scan it.
- AnnotationConfigApplicationContext: inherited GenericApplicationContext, realized AnnotationConfigRegistry interface, has the function of all of the above.
ClassPathXmlApplicationContext
It is also inherited AbstractApplicationContext, but relative to the AnnotationConfigApplicationContext, no AnnotationConfigApplicationContext powerful, For example, BeanDefinition can’t be registered
internationalization
Define a MessageSource
@Bean
public MessageSource messageSource(a) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
// Set the language configuration file prefix such as messages-en_cn and messages-en
messageSource.setBasename("messages");
return messageSource;
}
Copy the code
use
// Outputs the information in the corresponding language configuration file
annotationConfigApplicationContext.getMessage("test".null.new Locale("en_CN"))
Copy the code
Resource to load
ApplicationContext also has resource loading capabilities. For example, you can use ApplicationContext directly to retrieve the contents of a file
Resource resource = annotationConfigApplicationContext.getResource("file://D:\\IdeaProjects\\spring-framework\\zzf\\src\\main\\java\\com\\zzf\\entity\\People.java");
System.out.println(resource.contentLength());
Copy the code
The classpath to obtain
Resource resource = annotationConfigApplicationContext.getResource("classpath:com/zzf/entity/People.class");
System.out.println(resource.contentLength());
Copy the code
Get multiple at once
Resource[] resources = annotationConfigApplicationContext.getResources("classpath:com/zzf/service/*.class");
for (Resource resource : resources) {
System.out.println(resource.contentLength());
}
Copy the code
Get the runtime environment
// Get the operating system environment allowed by the JVM
annotationConfigApplicationContext.getEnvironment().getSystemEnvironment();
// Get some attributes of the JVM itself, including those set by -d
annotationConfigApplicationContext.getEnvironment().getSystemProperties();
// You can also get attributes directly from an environment or properties file
annotationConfigApplicationContext.getEnvironment().getProperty("xxx")
Copy the code
Event publishing
Define an event listener
@Bean
public ApplicationListener applicationListener(a) {
return new ApplicationListener() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("An event was received."); }}; }// Publish events
annotationConfigApplicationContext.publishEvent("XXX");
Copy the code
Publish event
Type conversion
PropertyEditor
A type conversion utility class provided in the JDK
public class StringToPeoplePropertyEditor extends PropertyEditorSupport implements PropertyEditor {
@Override
public void setAsText(String text) throws IllegalArgumentException {
People people = new People();
people.setName(text);
this.setValue(people); }}Copy the code
StringToPeoplePropertyEditor propertyEditor = new StringToPeoplePropertyEditor();
propertyEditor.setAsText("1");
People value = (People) propertyEditor.getValue();
System.out.println(value);
Copy the code
Register PropertyEditor in Spring
@Bean
public CustomEditorConfigurer customEditorConfigurer(a) {
CustomEditorConfigurer customEditorConfigurer = newCustomEditorConfigurer(); Map<Class<? >, Class<? extends PropertyEditor>> propertyEditorMap =new HashMap<>();
// Add a custom converter
propertyEditorMap.put(People.class, StringToPeoplePropertyEditor.class);
customEditorConfigurer.setCustomEditors(propertyEditorMap);
return customEditorConfigurer;
}
Copy the code
@Component
public class PeopleService {
/* * sets "true" to the name of people */
@Value("true")
People test;
public void test(a) { System.out.println(test); }}Copy the code
ConversionService
A type conversion service provided in Spring, which is more powerful than PropertyEditor
// Define the converter
public class StringToPeopleConverter implements ConditionalGenericConverter {
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return sourceType.getType().equals(String.class) && targetType.getType().equals(People.class);
}
@Override
public Set<ConvertiblePair> getConvertibleTypes(a) {
return Collections.singleton(new ConvertiblePair(String.class, People.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
People people = new People();
people.setName((String)source);
returnpeople; }}Copy the code
// Normal use
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringToPeopleConverter());
People value = conversionService.convert("1", People.class);
System.out.println(value);
Copy the code
Inject ConversionService into Spring
@Bean
public ConversionServiceFactoryBean conversionService(a) {
ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToPeopleConverter()));
return conversionServiceFactoryBean;
}
Copy the code
TypeConverter
Integrates the functions of PropertyEditor and ConversionService for internal use in Spring
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(People.class, new StringToPeoplePropertyEditor());
People value = typeConverter.convertIfNecessary("1", People.class);
System.out.println(value);
Copy the code
BeanPostProcessor
The Bean’s post-processor, which can interfere with the creation of each Bean, is a property of the BeanFactory, as detailed in the Bean lifecycle article.
BeanFactoryPostProcessor
The Bean factory’s post-handler is a property that belongs to the ApplicationContext. After the ApplicationContext instantiates a BeanFactory, You can use BeanFactoryPostProcessor to continue processing the BeanFactory. The BeanFactory can be set indirectly by the BeanFactoryPostProcessor. For example, CustomEditorConfigurer is a BeanFactoryPostProcessor. It allows you to add a custom PropertyEditor to the BeanFactory.
FactoryBean
Allows programmers to customize an object to become a Bean by placing it indirectly into the Spring container via FactoryBean. So what’s the difference between it and @bean? Because @bean can also customize an object to be a Bean. The difference is that FactoryBean is much more powerful, because you can implement other interfaces in Spring by defining an XxFactoryBean class. For example, if you implement the BeanFactoryAware interface, So you can get the Bean factory in your XxFactoryBean and do more with the Bean factory than you can with @bean.