Introduction to annotation development
Benefits of annotation development: use the form of annotation instead of xml configuration, completely eliminate the complex Spring configuration file from the project and simplify writing.
Disadvantages of annotation driven:
-
In order to achieve annotation driven purposes, the original simple writing may be made more complex.
-
It is very convenient to configure third-party development resources in XML, but annotation driven can not be edited in third-party development resources, so it will increase the development workload.
Common notes
Spring original annotation: it mainly replaces the configuration of < bean >.
annotation | explain |
---|---|
@Component | Used on classes to instantiate beans |
@Controller | Use to instantiate beans on web tier classes |
@Service | Used on the service layer class to instantiate beans |
@Repository | Used on dao layer classes to instantiate beans |
@Autowired | Use on field for type dependent injection |
@Qualifier | Used in conjunction with @ Autowired for dependency injection by name and reference type |
@Resource | Equivalent to @ Autowired + @Qualifier, inject reference types by name |
@Value | Inject properties of common types |
@Scope | Label the scope of the Bean |
@PostConstruct | Use to label the method, which is the initialization method of the Bean |
@PreDestroy | Use to mark the method as the Bean's destruction method |
Spring new annotation:
The above annotations cannot completely replace the xml configuration file. The configurations that need to be replaced by annotations are as follows:
- Configuration of non custom beans: < Bean >
- Load the configuration of the properties file: < context: Property placeholder >
- Configuration of component scan: < context: component scan >
- Import other files: < import >
annotation | explain |
---|---|
@Configuration | It is used to specify that the current class is a Spring configuration class, and annotations will be loaded from this class when creating a container. Used to specify the packages that Spring will scan when initializing the container. |
@ComponentScan | The function is the same as < context: component scan base package = "com. Itheima" / > in the xml configuration file of Spring. |
@Bean | On a method, annotations store the return value of the method in the Spring container. |
@PropertySource | Used to load the configuration in the. properties file. |
@Import | Used to import other configuration classes. |
Enable annotation
- Start annotation scanning and load the annotation items configured in the class:
<context:component-scan base-package="packageName"/>
-
explain:
-
When the package is scanned, all files in the configured package and its sub packages are scanned.
-
The scanning process is carried out in the form of folder recursive iteration.
-
The scan process reads only valid java files.
-
Only spring recognized annotations are read during scanning.
-
After the scan, the recognizable valid annotations will be converted into resources corresponding to spring and added to the IoC container.
-
-
be careful:
-
Whether in annotation format or XML configuration format, resources are ultimately loaded into the IoC container. The only difference is that the data is read in different ways.
-
In terms of loading efficiency, annotations are better than XML configuration files.
-
bean definitions: @ Component, @ Controller, @ Service, @ Repository
-
Type: class annotation
-
Location: above the class definition.
-
Function: set this class as a spring managed bean.
-
Example:
@Component public class ClassName{}
-
Note: @ Controller, @ Service, @ Repository are derived annotations of @ Component, and their functions are the same as those of @ Component.
-
Related properties:
- Value (default): defines the access id of the bean.
bean reference type attribute injection: @ Autowired, @ Qualifier
-
Type: attribute annotation, method annotation
-
Location: above the attribute definition and above the method definition.
-
Function: set the object of the corresponding property or reference the method, and transfer the type parameter.
-
Note: @ Autowired is assembled by type by default. After specifying @ Qualifier, you can specify the id of the assembled bean.
-
Related properties:
- required: defines whether the property is allowed to be null.
bean reference type attribute injection: @ Inject, @ Named, @ Resource
-
explain:
- @Inject and @ Named are annotations in the JSR330 specification. Their functions are exactly the same as @ Autowired and @ Qualifier, and are applicable to different architecture scenarios.
- @Resource is an annotation in JSR250 specification, which can simplify the writing format.
-
@Resource related properties:
-
name: set the id of the injected bean.
-
Type: sets the type of the injected bean, and the received parameter is Class type.
-
bean reference type attribute injection: @ Primary
-
Type: class annotation
-
Location: above the class definition.
-
Function: set the bean corresponding to the class to be assembled first when assembled by type.
-
Note: @ Autowired is assembled by type by default. When bean s of the same type appear, using @ Primary will increase the priority of automatic assembly by type, but multiple @ Primary will lead to invalid priority settings.
Non reference type property injection of bean: @ Value
-
Type: attribute annotation, method annotation
-
Location: above the attribute definition and above the method definition.
-
Function: set the value of the corresponding attribute or transfer parameters to the method.
-
explain:
-
The value value only supports non reference type data. When assigning values, all parameters of the method are assigned values.
-
The value value supports reading the property value in the properties file and passing the data in the properties into the class through the class property.
-
Value value supports spiel.
-
@If the value annotation is added above the attribute, the set method can be omitted (the purpose of the set method is to assign a value to the attribute).
-
Scope of bean: @ scope
-
Type: class annotation
-
Location: above the class definition.
-
Function: set this class as the scope attribute corresponding to the bean.
-
Related properties
- Value (default): defines the scope of the bean. The default is singleton.
bean life cycle: @ PostConstruct, @ PreDestroy
-
Type: Method annotation
-
Location: above the method definition.
-
Function: set this class as the corresponding lifecycle method of the bean.
Load third-party resources: @ Bean
-
Type: Method annotation
-
Location: above the method definition.
-
Function: set the return value of this method as a spring managed bean.
-
example:
@Bean("dataSource") public DruidDataSource createDataSource() { return ......; }
-
explain:
-
Because third-party beans cannot be modified on their source code, you can use @ Bean to solve the problem of introducing third-party beans.
-
This annotation is used to create bean s instead of static factories and instance factories in XML configuration, and does not distinguish whether the method is static or non static.
-
@The class where the Bean is located must be scanned and loaded by spring, otherwise the annotation cannot take effect.
-
-
Related properties
- Value (default): defines the access id of the bean.
Load properties file: @ PropertySource
-
Type: class annotation
-
Location: above the class definition.
-
Function: load the property value in the properties file.
-
example:
@PropertySource(value="classpath:jdbc.properties") public class ClassName { @Value("${propertiesAttributeName}") private String attributeName; }
-
Note: the * wildcard format is not supported. Once loaded, the corresponding attribute values can be used in all spring controlled bean s
-
Related properties
-
Value (default): sets the name of the loaded properties file.
-
ignoreResourceNotFound: whether to ignore if the resource is not found. The default value is false.
-
Pure annotation development: @ Configuration, @ ComponentScan
-
Type: class annotation
-
Location: above the class definition.
-
Function: set the current class to load the spring core configuration class (spring configuration file is no longer required).
-
example:
@Configuration
@ComponentScan("scanPackageName")
public class SpringConfigClassName{
}
- explain: - Core mating classes are used to replace spring Core configuration file. This class can be set to be empty without setting variables and properties. - bean Notes for scanning work @ComponentScan replace. - To load a pure annotation format context object, you need to use AnnotationConfigApplicationContext: ```java AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
Import third-party configuration: @ import
-
Type: class annotation
-
Location: above the class definition.
-
Function: import third-party bean s as spring controlled resources.
-
example:
@Configuration @Import(OtherClassName.class) public class ClassName { }
-
explain:
-
@The Import annotation can only be added once on the same class. If you need to Import more than one, you can set it in the form of array.
-
In the imported class, you can continue to use @ Import to Import other resources (see).
-
@The class of the bean can be imported into the spring container without declaring it as a bean.
-
Comprehensive case
maven dependency:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> </dependencies>
spring configuration class
DataSourceConfig.java:
package com.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; // Data source configuration class // Equivalent to < context: Property placeholder location = "classpath: JDBC. Properties" / >, and wildcards cannot be used* @PropertySource("classpath:jdbc.properties") public class DataSourceConfig { @Value("${jdbc.driver}") private static String driver; @Value("${jdbc.url}") private static String url; @Value("${jdbc.username}") private static String username; @Value("${jdbc.password}") private static String password; @Bean("dataSource") // Place the return value of the method in the Spring container public static DruidDataSource getDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } }
SpringConfig.java:
package com.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; // Spring core configuration class @Configuration @ComponentScan("com") // Equivalent to < context: component scan base package = "com" / > @Import({DataSourceConfig.class}) // Equivalent to < import resource = "" / > public class SpringConfig { }
dao layer
UserDaoImpl.java:
package com.dao.impl; import com.dao.UserDao; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; // Equivalent to < bean id = "userdao" ref = "com. Dao. Impl. Userdaoimpl" / > // @Component("userDao") @Repository("userDao") public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("UserDao save..."); } }
service layer
UserServiceImpl.java:
package com.service.impl; import com.dao.UserDao; import com.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; import javax.sql.DataSource; // Equivalent to < bean id = "userservice" ref = "com. Service. Impl. Userserviceimpl" / > // @Component("userService") @Service("userService") public class UserServiceImpl implements UserService { // <property name="userDao" ref="userDao"></property> // @Autowired / / can be used separately and matched from the spring container according to the data type (there will be a matching problem when there are multiple bean s with the same data type) // @Qualifier("userDao") / / the id of the specified bean is matched from the spring container and used in combination with @ Autowired @Resource(name="userDao") // Equivalent to @ Autowired+@Autowired UserDao userDao; @Resource(name="dataSource") DataSource dataSource; @Value("${jdbc.driver}") // Read the value in the configuration file private String driver; /* The set method can be omitted when using annotation development, but cannot be omitted when using configuration file public void setUserDao(UserDao userDao) { this.userDao = userDao; } */ @Override public void save() { System.out.println("driver: "+driver); System.out.println("dataSource: "+dataSource); userDao.save(); } @PostConstruct public void init() { System.out.println("service Object initialization method"); } @PreDestroy public void destroy() { System.out.println("service Object destruction method"); } }
controller layer
App.java:
package com.controller; import com.config.SpringConfig; import com.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class App { public static void main(String[] args) { // ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = (UserService)context.getBean("userService"); userService.save(); context.close(); } }
Operation results:
service Object initialization method dataSource: { CreateTime:"2021-12-03 01:05:00", ActiveCount:0, PoolingCount:0, CreateCount:0, DestroyCount:0, CloseCount:0, ConnectCount:0, Connections:[ ] } UserDao save... service Object destruction method
Integrate third-party technology
Annotation integration Mybatis
Note the development steps of integrating MyBatis:
- Modify the format of mybatis external configuration file to annotation format;
- The business class uses @ Component to declare bean s and @ Autowired to inject objects;
- Create configuration files JDBCConfig and MyBatisConfig classes and import them into the core configuration class SpringConfig;
- Enable annotation scanning;
- Use the AnnotationConfigApplicationContext object to load configuration items.
The core contents are as follows:
- Maven dependency:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.8.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency>
- MybatisConfig.java (Mybatis configuration class):
package com.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; public class MybatisConfig { /* <!-- spring After integrating mybatis, create objects for connection -- > <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="typeAliasesPackage" value="com.domain"/> </bean> <!-- Scan the mybatis mapping configuration and manage it as a spring bean -- > <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.dao"/> </bean> */ // The following annotation replaces the content of the above configuration file: the return value will be used as the bean of the Spring container @Bean public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); sqlSessionFactoryBean.setTypeAliasesPackage("com.domain"); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer getMapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.dao"); return mapperScannerConfigurer; } }
- SpringConfig.java (Spring core configuration class):
package com.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @ComponentScan("com") // Equivalent to < context: component scan base package = "com" / > @Import({DataSourceConfig.class, MybatisConfig.class}) // Equivalent to < import resource = "" / > public class SpringConfig { }
Annotation integration Junit
Annotation integration Junit development steps:
- Spring takes over the running rights of Junit and uses the Junit class loader dedicated to spring;
2. Set the corresponding Spring container for Junit test cases:
-
After Spring 5.0, Junit version must be 4.12 or above.
-
Junit is only used for unit testing. Junit's test class cannot be configured as a Spring bean, otherwise the configuration will be packaged into the project.
Example: integrating Junit5
- Maven dependency:
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.9.RELEASE</version> </dependency>
- Test class:
package com.service; import com.config.SpringConfig; import com.domain.User; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.List; // Set the spring specific class loader @ExtendWith(SpringExtension.class) // Set the configuration corresponding to the loaded spring context @ContextConfiguration(classes=SpringConfig.class) public class UserServiceTest { @Autowired UserService userService; @Test public void testFindById() { User user = userService.findById(1); // System.out.println(user); Assertions.assertEquals("Mick", user.getName()); } @Test public void testFindAll() { List<User> users = userService.findAll(); Assertions.assertEquals(3, users.size()); } }
IoC underlying core principles
IoC core interface
Component scanner: @ ComponentScan
Component scanner: during the development process, you need to load the necessary beans or exclude the specified beans according to the requirements.
Application scenario:
- Data layer interface test
- Business layer interface test
- Various operating environment settings
Configure scanner
-
Name: @ ComponentScan
-
Type: class annotation
-
Location: above class definition
-
Function: set spring configuration loading class scanning rules
-
example:
@Configuration @ComponentScan( value="com", // Set basic scan path excludeFilters = // Set filtering rules. Currently, it is exclude filtering @ComponentScan.Filter( // catalog filter type= FilterType.ANNOTATION, // Set the filtering method to filter by annotation classes=Repository.class) // Set specific filter items. If all @ Repository decorated bean s are not loaded ) public class SpringConfig { }
-
includeFilters: sets inclusive filters
-
excludeFilters: sets exclusive filters
-
Type: sets the filter type (filter Policy)
- ANNOTATION
- ASSIGNABLE_TYPE
- ASPECTJ
- REGEX
- CUSTOM
Custom scanner
-
Name: TypeFilter
-
Type: Interface
-
Role: custom type filter
Example:
- Custom scanner
public class MyTypeFilter implements TypeFilter { public boolean match(MetadataReader mr, MetadataReaderFactory mrf) throws IOException { ClassMetadata cm = metadataReader.getClassMetadata(); tring className = cm.getClassName(); if(className.equals("com.itheima.dao.impl.BookDaoImpl")){ return true; // Filter (intercept) } return false; // No filtering (release) } }
- Configuration class:
@Configuration @ComponentScan( value = "com", excludeFilters = @ComponentScan.Filter( type= FilterType.CUSTOM, classes = MyTypeFilter.class ) ) public class SpringConfig { }
Custom importer: ImportSelector
Only through configuration can bean s enter the spring container, be loaded and controlled by spring. Beans are configured as follows:
-
Use < bean / > tag configuration in XML file
-
Use @ Component and derived annotation configuration
In the process of enterprise development, you usually need to configure a large number of beans, so you need a way to configure a large number of beans quickly and efficiently.
ImportSelector annotation:
-
Type: Interface
-
Function: Custom bean importer (import beans without @ Component annotation)
Example:
- Custom importer:
public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata icm) { // Returns the array of beans to be imported. The bean can be scanned and recognized even without @ Component annotation return new String[]{"com.dao.impl.AccountDaoImpl"}; } }
- Configuration class:
@Configuration @ComponentScan("com") @Import(MyImportSelector.class) // Import custom importer public class SpringConfig { }
Encapsulation tool class of custom importer:
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AspectJTypeFilter; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; public class CustomerImportSelector implements ImportSelector { private String expression; public CustomerImportSelector(){ try { //Specify the name of the loaded properties file during initialization Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties"); //Sets the name of the loaded property expression = loadAllProperties.getProperty("path"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //1. Define the name of the scan package String[] basePackages = null; //2. Judge whether there is @ ComponentScan annotation on the class with @ Import annotation if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) { //3. Take out the attribute of @ ComponentScan annotation Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName()); //4. Get the value of the basePackages attribute with the attribute name basePackages = (String[]) annotationAttributes.get("basePackages"); } //5. Judge whether there is this attribute (if there is no ComponentScan annotation, the attribute value is null; if there is ComponentScan annotation, basePackages defaults to an empty array) if (basePackages == null || basePackages.length == 0) { String basePackage = null; try { //6. Fetch the package name containing the @ Import annotation class basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName(); } catch (ClassNotFoundException e) { e.printStackTrace(); } //7. Store in array basePackages = new String[] {basePackage}; } //8. Create a classpath scanner ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); //9. Create a type filter (pointcut expression type filter is used here) TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader()); //10. Add a type filter to the scanner scanner.addIncludeFilter(typeFilter); //11. Create a collection of fully qualified class names Set<String> classes = new HashSet<>(); //12. Populate set data for (String basePackage : basePackages) { scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName())); } //13. Return according to the rules return classes.toArray(new String[classes.size()]); } }
Custom registrar: ImportBeanDefinitionRegistrar
-
Type: Interface
-
Role: Customize bean definition register (identify beans marked with @ Component)
Example:
- Custom registrar:
// Indicates that all bean s under the com directory are registered public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata icm, BeanDefinitionRegistry r) { ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(r, false); TypeFilter tf = new TypeFilter() { public boolean match(MetadataReader mr, MetadataReaderFactory mrf) throws IOException { return true; } }; scanner.addIncludeFilter(tf); // contain // scanner.addExcludeFilter(tf); // exclude scanner.scan("com"); } }
- Configuration class:
@Configuration @Import(MyImportBeanDefinitionRegistrar.class) // Equivalent to @ ComponentScan("com") public class SpringConfig { }
Encapsulation tool class:
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AspectJTypeFilter; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; import java.util.Map; import java.util.Properties; public class CustomeImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { private String expression; public CustomeImportBeanDefinitionRegistrar(){ try { //Specify the name of the loaded properties file during initialization Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties"); //Sets the name of the loaded property expression = loadAllProperties.getProperty("path"); } catch (IOException e) { e.printStackTrace(); } } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //1. Define the name of the scan package String[] basePackages = null; //2. Judge whether there is @ ComponentScan annotation on the class with @ Import annotation if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) { //3. Take out the attribute of @ ComponentScan annotation Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName()); //4. Get the value of the basePackages attribute with the attribute name basePackages = (String[]) annotationAttributes.get("basePackages"); } //5. Judge whether there is this attribute (if there is no ComponentScan annotation, the attribute value is null; if there is ComponentScan annotation, basePackages defaults to an empty array) if (basePackages == null || basePackages.length == 0) { String basePackage = null; try { //6. Fetch the package name containing the @ Import annotation class basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName(); } catch (ClassNotFoundException e) { e.printStackTrace(); } //7. Store in array basePackages = new String[] {basePackage}; } //8. Create a classpath scanner ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false); //9. Create a type filter (pointcut expression type filter is used here) TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader()); //10. Add a type filter to the scanner scanner.addIncludeFilter(typeFilter); //11. Scan the specified package scanner.scan(basePackages); } }
bean initialization process parsing
bean unified initialization
-
BeanFactoryPostProcessor
-
Function: defines the actions to be executed after the bean factory object is created and before the bean object is created. It is used for post creation business processing of the factory.
-
Running time: the current operation is used to process the plant and only runs once.
-
-
BeanPostProcessor
-
Function: defines the unified actions before and after initialization of all beans, which are used for pre creation business processing and post creation business processing of beans.
-
Run time: the current operation is accompanied by the creation process of each bean. This operation is run every time a bean is created.
-
-
InitializingBean
-
Function: defines the action before initialization of each bean, which belongs to non-uniform action and is used for business processing before bean creation.
-
Running time: the current operation is accompanied by the creation process of any bean to ensure its personalized business processing.
-
-
Note: the above operations need to be loaded by the spring container before they can run.
Example:
- BeanFactoryPostProcessor:
package com.post; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class MyBeanFactory implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { System.out.println("Bean The factory made it"); } }
- BeanPostProcessor:
package com.post; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBean implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("bean Before balabalabala"); System.out.println(beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("bean Then balabalabala"); return bean; } }
- InitializingBean:
package com.service.impl; import com.dao.UserDao; import com.domain.User; import com.service.UserService; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; @Service("userService") public class UserServiceImpl implements InitializingBean { // Defines the initialization operation of the current bean, which is equivalent to the init method attribute configuration @Override public void afterPropertiesSet() throws Exception { System.out.println("UserServiceImpl......bean ...init......"); } }
- Operation results:
Bean The factory made it bean Before balabalabala springConfig bean Then balabalabala bean Before balabalabala com.config.DataSourceConfig bean Then balabalabala bean Before balabalabala dataSource bean Then balabalabala bean Before balabalabala getSqlSessionFactoryBean bean Then balabalabala bean Then balabalabala bean Before balabalabala userDao bean Then balabalabala bean Then balabalabala bean Before balabalabala userService UserServiceImpl......bean ...init...... bean Then balabalabala bean Before balabalabala com.service.UserServiceTest.ORIGINAL bean Then balabalabala
Single bean initialization
- FactoryBean: encapsulates the initialization process of a single bean to simplify configuration.
Difference between FactoryBean and BeanFactory:
-
FactoryBean: encapsulates the creation process of a single bean. This is usually preparation for creating another bean.
-
BeanFactory: the top-level interface of Spring container, which uniformly defines bean related acquisition operations.
Example:
import org.springframework.beans.factory.FactoryBean; public class UserServiceImplFactoryBean implements FactoryBean { // Key: return data @Override public Object getObject() throws Exception { return new UserServiceImpl(); } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return false; } }