Article directory
- 1. BeanDefinition
- 2. BeanDefinitionReader
-
- 2.1. AnnotatedBeanDefinitionReader
- 2.2.XmlBeanDefinitionReader
- 5. ClassPathBeanDefinitionScanner
- 6. BeanFactory
- 7. ApplicationContext
-
- 7.1. AnnotationConfigApplicationContext
- 7.2. ClassPathXmlApplicationContext
- 8. Type conversion
-
- 8.1.PropertyEditor
- 8.2.ConversionService
- 8.3. TypeConverter
- 9. FactoryBean
- 10. ExcludeFilter and IncludeFilter
- 11. MetadataReader, ClassMetadata, AnnotationMetadata
Prepare the test object User in advance:
public class User {<!-- --> public User(int flag, String uuid){<!-- --> System.out.println(flag + "----------" + uuid); } public User(){<!-- --> System.out.println("User no parameter construction"); } }
1. BeanDefinition
BeanDefinition represents the definition of a Bean, which can record the characteristics of the Bean, for example:
- Bean type: beanClass attribute
- Bean scope: Scope attribute
- Whether the bean is lazy loaded: lazyinit attribute
…
In Spring, the main ways to define a bean are: using bean tags in XML files to define its bean properties. In addition, you can use @Bean annotations and @Component annotations to define annotations. Of course, you can also use programmatic definitions. Bean, the following code:
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); //Define a BeanDefinition object AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); //Add object information to the BeanDefinition object beanDefinition.setBeanClass(User.class); beanDefinition.setScope("prototype"); //Add the BeanDefinition object to the Spring container context.registerBeanDefinition("user",beanDefinition); System.out.println("The user object created by Spring BeanDefinition is: " + context.getBean("user")); UserService userService = (UserService) context.getBean("userService"); userService.test(); } }
2. BeanDefinitionReader
It represents the BeanDefinition reader. There are two main reading methods:
2.1, AnnotatedBeanDefinitionReader
This component can directly convert certain types into BeanDefinition, and will parse the annotations on the class. The test code is as follows:
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); //Declare a BeanDefinition reader and pass in the Spring container in this reader AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context); annotatedBeanDefinitionReader.register(User.class); System.out.println("BeanDefinition reader AnnotatedBeanDefinitionReader creates a bean as: " + context.getBean("user")); UserService userService = (UserService) context.getBean("userService"); userService.test(); } }
2.2, XmlBeanDefinitionReader
This interface mainly performs BeanDefinition conversion by parsing the Bean tags in the XML file. The code is as follows:
XML configuration file information:
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); //Declare a BeanDefinition reader and pass in the Spring container in this reader XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context); int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml"); System.out.println("Number of bean tags scanned: " + i); System.out.println("BeanDefinition readerXmlBeanDefinitionReader creates a bean as: " + context.getBean("user")); UserService userService = (UserService) context.getBean("userService"); userService.test(); } }
5. ClassPathBeanDefinitionScanner
It is a BeanDefinition resource scanner. Its function is similar to that of BeanDefinitionReader. The only difference is that it scans class resources in a specified path and parses the scanned classes to see if they contain relevant annotation information. For example: if the class contains @Component annotation, the class will be put into the Spring container as a BeanDefinition object. The code is as follows:
@Component public class UserService {<!-- --> public void test(){<!-- --> System.out.println("test--->Spring creates object"); } }
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.refresh(); //Declare a BeanDefinition reader and pass in the Spring container in this reader ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); int scan = scanner.scan("com.practice.service"); System.out.println("The number of bean resources scanned under the specified path: " + scan); System.out.println("ClassPathBeanDefinitionScanner scanner creates bean: " + context.getBean("userService")); } }
6. BeanFactory
BeanFactory will be responsible for creating beans and providing APIs for obtaining beans.
7. ApplicationContext
ApplicationContext is a type of BeanFactory, which is defined in Spring’s source code as:
ListableBeanFactory and HierarchicalBeanFactory in the figure both inherit from BeanFactory, so ApplicationContext also has the features and functions of BeanFactory. However, ApplicationContext also has additional functions, such as supporting internationalization, supporting obtaining environment information, supporting event publishing and related resource loading. It has two implementation classes, as introduced below
7.1, AnnotationConfigApplicationContext
Its source code is as follows:
AnnotationConfigApplicationContext inherits GenericApplicationContext, implements the AnnotationConfigRegistry interface, and has all the functions of its parent class, parent interface, and even higher-level interfaces inherited from the parent interface.
7.2, ClassPathXmlApplicationContext
It inherits AbstractApplicationContext, but compared to AnnotationConfigApplicationContext, its functions are not as powerful as AnnotationConfigApplicationContext. For example, BeanDefinition cannot be registered.
8. Type conversion
In Spring, there may be some type conversion problems. Spring provides some technologies to facilitate type conversion operations. In the Spring source code, there are many type conversion operations. Type conversion mainly has the following interfaces.
8.1, PropertyEditor
This is the type conversion tool class that comes with JDK. The specific usage is as follows:
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {<!-- --> @Override public void setAsText(String text) throws IllegalArgumentException {<!-- --> User user = new User(); user.setName(text); this.setValue(user); } }
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor(); propertyEditor.setAsText("1"); User value = (User) propertyEditor.getValue(); System.out.println(value); } }
8.2, ConversionService
The type conversion service provided in Spring is more powerful than PropertyEditor. Its code is as follows:
public class StringToUserConverter implements ConditionalGenericConverter {<!-- --> @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {<!-- --> return sourceType.getType().equals(String.class) & amp; & amp; targetType.getType().equals(User.class); } @Override public Set<ConvertiblePair> getConvertibleTypes() {<!-- --> return Collections.singleton(new ConvertiblePair(String.class, User.class)); } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {<!-- --> User user = new User(); user.setName((String)source); return user; } }
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> DefaultConversionService conversionService = new DefaultConversionService(); conversionService.addConverter(new StringToUserConverter()); User value = conversionService.convert("1", User.class); System.out.println(value); } }
8.3, TypeConverter
It integrates the functions of PropertyEditor and ConversionService and is used internally by Spring, as follows:
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) {<!-- --> SimpleTypeConverter typeConverter = new SimpleTypeConverter(); typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor()); User value = typeConverter.convertIfNecessary("1", User.class); System.out.println(value); } }
9. FactoryBean
We want to create a Bean completely by us, which can be done through FactoryBean, as follows:
public class factoryBeanTest implements FactoryBean {<!-- --> @Override public Object getObject() throws Exception {<!-- --> UserService userService = new UserService(); return userService; } @Override public Class<?> getObjectType() {<!-- --> return UserService.class; } }
Through the above code, we created a UserService object ourselves, and it will become a Bean. However, the UserService Bean created in this way will only be initialized and will not go through other Spring life cycle steps, such as dependency injection.
10. ExcludeFilter and IncludeFilter
These two Filters are used for filtering during Spring scanning. ExcludeFilter means to exclude the filter, and IncludeFilter means to include the filter, as follows:
FilterType is divided into:
1. ANNOTATION: Indicates whether an annotation is included
2. ASSIGNABLE_TYPE: Indicates whether it is a certain class
3. ASPECTJ: Indicates whether it conforms to an Aspectj expression
4. REGEX: Indicates whether it matches a certain regular expression
5. CUSTOM: Customization
11. MetadataReader, ClassMetadata, AnnotationMetadata
In Spring, it is necessary to parse class information, such as class name, methods in the class, and annotations on the class. These can be called metadata of the class, so Spring abstracts the metadata of the class and provides some tools
MetadataReader represents the metadata reader of the class, and the default implementation class is SimpleMetadataReader. The code is as follows:
package com.practice.service; import org.springframework.stereotype.Component; @Component public class UserService {<!-- --> public void test(){<!-- --> System.out.println("test--->Spring creates object"); } }
//Spring core concept test class public class TestSpringDemo {<!-- --> public static void main(String[] args) throws IOException {<!-- --> SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory(); //Construct a MetadataReader MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.practice.service.UserService"); // Get a ClassMetadata and get the class name ClassMetadata classMetadata = metadataReader.getClassMetadata(); System.out.println(classMetadata.getClassName()); // Get an AnnotationMetadata and get the annotation information on the class AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); for (String annotationType : annotationMetadata.getAnnotationTypes()) {<!-- --> System.out.println(annotationType); } } }
Note: SimpleMetadataReader uses ASM technology when parsing classes. Because Spring needs to scan when it starts, if the specified package path is relatively broad, then there will be a lot of scanned classes. If all these classes are loaded into the JVM when Spring starts, this is not good, so use ASM technology.