Chapter 01 Spring Foundation and Component Usage
What is Section 01-Spring?
Spring focuses on J2EE solutions, not just one layer of solutions. Spring is a “one-stop shop” for enterprise application development, spanning the presentation, business, and persistence layers. However, Spring does not want to replace existing frameworks, but rather integrate them with a high degree of openness.
Spring used IoC container and DI dependency injection most early. By configuring bean tags in the application. XML file, components or objects in the project are handed over to the IoC container for management. This results in a large project with a large number of bean tags to configure, which can be cumbersome to maintain.
Spring Core Architecture
- Spring Core: That is, the Spring Core, which is the most basic part of the framework and provides IOC and dependency injection features
- Spring Context: That is, the Spring Context container, which is a BeanFactory enhanced subinterface
- Spring Web: It provides support for Web application development
- Spring MVC: It is an implementation of the MVC idea in Web applications
- Spring DAO: Provides an abstraction layer for JDBC, simplifying JDBC coding and making coding more robust.
- Spring ORM: It supports integration for popular ORM frameworks such as Spring + Hibernate, Spring + iBatis, Spring + JDO integration, and so on.
Common Spring Components
Section 02 – XML and annotation register beans
Create maven project, add dependency add Entity package, add entity class Person
public class Person {
private String name;
private Integer age;
/ / omit getter/setter/toString
}
Copy the code
XML configuration register beans
Create a new beans.xml configuration file in the Resource directory
<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="person" class="com.citi.entity.Person">
<property name="name" value="Peter"></property>
<property name="age" value="18"></property>
</bean>
</beans>
Copy the code
Create a new SingleBeanContainerTest test class under Test Pacakge, add the main method, and call getBeanByXml() to test getting the bean from the container
public static void getBeanByXml(a){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
Person person = (Person) context.getBean("person");
System.out.println(person);
}
Copy the code
Console printing
Add the configuration class BeanConfig to the config package by registering beans with annotations
@Configuration
public class BeanConfig {
@Bean
public Person person(a){
Person person = new Person();
person.setName("Stark");
person.setAge(40);
returnperson; }}Copy the code
@configuration: identifies a Configuration class, which is equivalent to a Configuration file. @bean: Registers a Bean to the container with the type of the returned value and the id of the returned value SingleBeanContainerTest. The new method is executed in the main method
public static void getBeanByAnno(){ ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); Person person = (Person) context.getBean("person"); System.out.println(person); String[] beanNamesForType = context.getBeanNamesForType(Person.class); for (String s : beanNamesForType) { System.out.println("Bean id:" + s); }}Copy the code
Console output
Change the method name of the @bean annotation in BeanConfig to stark
@Bean
public Person stark(a){
Person person = new Person();
person.setName("Stark");
person.setAge(40);
return person;
}
Copy the code
Error: No bean named ‘person’ available
“Person” = “person”; “person” = “stark”; “person” = “person”; “stark” = “person”
In addition to changing the method name under the @bean annotation to define the Bean ID, you can also define the Bean name by @bean (“thor”)
Add data to the Map using put(“key”,value). Key is the id of the Bean. Value is the object.
Section 03 – BATCH register beans with annotations
@compponmentScan replaces @bean to add controller, Service and DAO packages respectively and add responding classes. The three classes are declared as beans by @Controller, @Service and @repository annotations
@Controller
public class PersonController {}Copy the code
@Service
public class PersonService {}Copy the code
@Repository
public class PersonDao {}Copy the code
Add the @ComponentScan annotation to BeanConfig to scan all the beans under the com.citi package into the BeanConfig configuration class. This is equivalent to having many Bean tags in an XML configuration file. All beans can be scanned with a single annotation
@Configuration
@ComponentScan(basePackages = "com.citi")
public class BeanConfig {
}
Copy the code
Add a New ComponentScanTest test class to test whether the IoC container instantiates scanned beans
public class ComponentScanTest {
@Test
public void getBeansByScan(a){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for(String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); }}}Copy the code
The console output is as follows: the three custom classes, including BeanConfi itself, are instantiated by the container
The Person class in the Entity package is not instantiated because there is no annotation on the Person class, so it is not registered in the container and therefore is not instantiated. Add an @Component annotation to the Person entity class to identify it as a bean. The test method is executed again, and the console prints the following result, with the Person class instantiated
@ ComponentScan source
The use of includeFilters ()
IncludeFilters () and excludeFilters() return a Filter array
FilterType is an enumerated class, default is ANNOTATION, ANNOTATION mode
Modify the BeanConfig code and add includeFilters() to scan only beans identified by the @controller, @service annotation below the com.citi package. Don’t forget to useDefaultFilters = false
@Configuration
@ComponentScan(basePackages = "com.citi", includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) }, useDefaultFilters = false)
public class BeanConfig {}Copy the code
When the test is executed, the console outputs only beans with @Controller, @Service annotations, @Componet, and @Repository annotations that are not container-managed
Plus: Why useDefaultFilters = false when using includeFilters?
When useDefaultFilters = true, it goes into the registerDefaultFilters() method
This method adds the @Component-annotated beans into the includeFilters, while @controller, @Service, and @Repository are all based on @Component annotations. All useDefaultFilters = true will cause beans set to scan for @Controller and @Service annotations not to take effect
Set BeanConfig includeFilters () to excludeFilters() and useDefaultFilters = true. Instantiation object of a Bean other than the @service annotated Bean
Filter beans using ASSIGNABLE_TYPE in the FilterType enumerated class and modify BeanConfig to the following to indicate that beans other than PersonController and PersonService are being accessed
@Configuration
@ComponentScan(basePackages = "com.citi", excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {PersonController.class, PersonService.class}) }, useDefaultFilters = true)
public class BeanConfig {}Copy the code
Using a custom FilterType, CustTypeFilter is added to the config package, inheriting TypeFilter
public class CustTypeFilter implements TypeFilter {
/ * * *@paramMetadataReader reads information about the class currently being scanned *@paramMetadataReaderFactory can get information for any other class *@return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// Get the annotation information for the current class
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// Get information about the classes currently being scanned
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// Get the current class resource (class path)
Resource resource = metadataReader.getResource();
// Get the class name
String className = classMetadata.getClassName();
// Scan the class
System.out.println("-- -- -- -- -- - >" + className);
Return true to filter out beans that meet this condition
if (className.contains("service")) {return true;
}
return false; }}Copy the code
In addition to @ComponentScan, you can also add @ComponentScans
Two @ComponentScan annotations are used, one to remove custom beans whose Bean ID contains the “service” string, and the other to remove beans marked with the @Controller Annotation using the Filter Annotation type
@ComponentScans({@ComponentScan(basePackages = "com.citi", excludeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {CustTypeFilter.class}) }, useDefaultFilters = true), @ComponentScan(basePackages = "com.citi", excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) }, useDefaultFilters = true)})
public class BeanConfig {}Copy the code
The console should output an instantiated object with the exception of PeresonController and PersonService. According to the console print, the two @ComponentScan configurations are not in effect.
Section 04-bean single-instance and multi-instance
IoC containers, whether annotated or XML, are single-instance by default and are created when the IoC container is initialized. Multi-instances are created only when the bean is used
@Configuration
public class BeanConfig {
@Bean
public Person person(a){
Person person = new Person();
person.setName("Stark");
person.setAge(40);
returnperson; }}Copy the code
New test class SingleOrMultInstanceTest, perform testSingleBean () method
public class SingleOrMultiInstanceTest { @Test public void testSingleBean(){ ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); Person person = (Person) context.getBean("person"); Person person1 = (Person) context.getBean("person"); System.out.println(" single instance: "+ (person == person1)); }}Copy the code
View the output by comparing the two beans retrieved from the container to see if they are one bean, which is singleton by default
The @scope annotation allows you to configure a Bean to be single-instance or multi-instance
Modify BeanConfig
@Configuration
public class BeanConfig {
@Bean
@Scope("prototype")
public Person person(a){
Person person = new Person();
person.setName("Stark");
person.setAge(40);
returnperson; }}Copy the code
Execute the test, which is now multi-instance
Section 05 – Lazy loading @Lazy
Modify BeanConfig to add @lazy annotation, Lazy loading pointer to multi-singleton Bean, because singleton is created when container initialization, add @lazy annotation, The container instantiates the Bean when it calls getBean() to get the instantiated object first annotating the @Scope annotation in BeanConfig
@Configuration
public class BeanConfig {
//@Lazy
@Bean
//@Scope("prototype")
public Person person(a){
System.out.println("Bean is instantiated");
Person person = new Person();
person.setName("Stark");
person.setAge(40);
returnperson; }}Copy the code
New LazyLoadTest, testLazyLoad() method that contains only container initialization code
public class LazyLoadTest {
@Test
public void testLazyLoad(a){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
//Person person = (Person) context.getBean("person");
//System.out.println(person);}}Copy the code
Looking at the console, the Bean is instantiated, indicating that the Bean is instantiated when the container is initialized
Release the @lazy annotation in BeanConfig, and again, the Bean is not instantiated
Add the code to get the Bean in the testLazyLoad() method of the LazyLoadTest class
public class LazyLoadTest {
@Test
public void testLazyLoad(a){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
Person person = (Person) context.getBean("person"); System.out.println(person); }}Copy the code
After the @lazy annotation is added, the container initializes the Bean instead of instantiating it on getBean