2. Bottom Notes
2.1 Container function
2.1.1. @Configuration
2.2.1.1.Basic Use
User.java
package cn.com.springboot.demo.bean; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; /** * User information. * * @author J */ @Setter @Getter @ToString @NoArgsConstructor public class User { /** Full name */ private String name; /** Age */ private String age; public User(String name, String age) { this.name = name; this.age = age; } }
Pet.java
package cn.com.springboot.demo.bean; import lombok.*; /** * Pet information. * * @author J */ @Setter @Getter @ToString @NoArgsConstructor public class Pet { /** * Varieties */ private String breed; /** * Nickname? */ private String petName; public Pet(String breed, String petName) { this.breed = breed; this.petName = petName; } }
MyConfig01.java
package cn.com.springboot.demo.config; import cn.com.springboot.demo.bean.Pet; import cn.com.springboot.demo.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * The first configuration class example. * * @author J */ @Configuration public class MyConfig01 { /** * Declare a component with an ID of user01. */ @Bean public User user01() { return new User("Zhang San", "27"); } /** * Declare a component with an ID of myPet. */ @Bean("myPet") public Pet pet01() { return new Pet("cat", "27"); } }
- @Configuration: Tell spring-boot that this is a configuration class, which is a configuration file
- @Bean: Register the method as a component and add it to the container
- Component ID: The method name is the component ID of this component
- Return value: component instance in container
- @Bean("myPet"): Component with ID defined as myPet
- The configuration class itself is a component
- Registered component, single-instance by default
MainApp.java
package cn.com.springboot.demo; import cn.com.springboot.demo.bean.Pet; import cn.com.springboot.demo.bean.User; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApp { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args); User user01 = run.getBean("user01", User.class); Pet myPet = run.getBean("myPet", Pet.class); System.out.println(user01); System.out.println(myPet); } }
Run Results
User(name=Zhang San, age=27) Pet(breed=cat, petName=27)
2.2.1.2.Full Mode and Lightweight Mode
The @Configuration annotation has the following additional properties in spring-boot 2:
... boolean proxyBeanMethods() default true; ...
The default value is true. If @Configuration(proxyBeanMethods = true), then the method is invoked using a proxy object. spring-boot always checks if the component exists in a container and returns it if it exists to guarantee a single instance of the component. If @Configuration(proxyBeanMethods = false), the above checks are skipped, and each time a component is called, a new component is returned.
- Full Mode: proxyBeanMethods = true
- Configured component If there is a dependency, method calls single-instance component
- Lite Mode: proxyBeanMethods = false
- Configured components without dependencies skip the checking process to speed up container startup
Sample Code
proxyBeanMethods = true:
MyConfig01.java
package cn.com.springboot.demo.config; import cn.com.springboot.demo.bean.Pet; import cn.com.springboot.demo.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * The first configuration class example. * * @author J */ @Configuration(proxyBeanMethods = true) public class MyConfig01 { /** * Declare a component with an ID of user01. */ @Bean public User user01() { return new User("Zhang San", "27"); } /** * Declare a component with an ID of myPet. */ @Bean("myPet") public Pet pet01() { return new Pet("cat", "27"); } }
MainApp.java
package cn.com.springboot.demo; import cn.com.springboot.demo.bean.User; import cn.com.springboot.demo.config.MyConfig01; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApp { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args); // Testing Full Mode and Lite Mode for MyConfig01 MyConfig01 bean = run.getBean(MyConfig01.class); User user01 = bean.user01(); User user02 = bean.user01(); System.out.println("Full Mode: " + (user01 == user02)); } }
Run Results
Full Mode: true
proxyBeanMethods = false:
MyConfig01.java
package cn.com.springboot.demo.config; import cn.com.springboot.demo.bean.Pet; import cn.com.springboot.demo.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * The first configuration class example. * * @author J */ @Configuration(proxyBeanMethods = false) public class MyConfig01 { /** * Declare a component with an ID of user01. */ @Bean public User user01() { return new User("Zhang San", "27"); } /** * Declare a component with an ID of myPet. */ @Bean("myPet") public Pet pet01() { return new Pet("cat", "27"); } }
MainApp.java
package cn.com.springboot.demo; import cn.com.springboot.demo.bean.User; import cn.com.springboot.demo.config.MyConfig01; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApp { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args); // Testing Full Mode and Lite Mode for MyConfig01 MyConfig01 bean = run.getBean(MyConfig01.class); User user01 = bean.user01(); User user02 = bean.user01(); // System.out.println("Full Mode: " + (user01 == user02)); System.out.println("Lite Mode: " + (user01 == user02)); } }
Run Results
Lite Mode: false
2.2.1.3.Other notes of the same type
Notes previously used to register components can also be used, such as:
@Component // A generic term for a component that is handed over to Spring management @Controller // Act on the controller and leave the component to Spring management @Service // Acts on a logical implementation class, handing it over to Spring management @Repository // Hand over the implementation class of the interface to Spring management on the interface that acts on the persistence layer @ComponentScan // Define package scan rules
2.1.2. @Import
2.2.1.1.Basic Use
Imports components of the specified type into a container by calling the parameterless construction of the specified class, which can be passed multiple arrays, such as:
Example
MyConfig01.java
package cn.com.springboot.demo.config; /** * The second configuration class example. * * Demo@Import * @author J */ import ch.qos.logback.core.db.DBHelper; import cn.com.springboot.demo.bean.User; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Import({User.class, DBHelper.class}) @Configuration public class MyConfig02 {}
MainApp.java
package cn.com.springboot.demo; import ch.qos.logback.core.db.DBHelper; import cn.com.springboot.demo.bean.User; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import java.util.Arrays; @SpringBootApplication public class MainApp { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args); // Testing Full Mode and Lite Mode for MyConfig01 // MyConfig01 bean = run.getBean(MyConfig01.class); // User user01 = bean.user01(); // User user02 = bean.user01(); // System.out.println("Full Mode: " + (user01 == user02)); // System.out.println("Lite Mode: " + (user01 == user02)); // System.out.println("---------------------------------------"); String[] beans = run.getBeanNamesForType(User.class); Arrays.asList(beans).forEach(System.out::println); String[] beans2 = run.getBeanNamesForType(DBHelper.class); Arrays.asList(beans2).forEach(System.out::println); } }
Run Results
cn.com.springboot.demo.bean.User ch.qos.logback.core.db.DBHelper
- Default name of @Import import component: full class name
- Example: ch.qos.logback.core.db.DBHelper
2.1.3. @Conditional
Components are only injected into containers when certain conditions are met. @Conditional has many derived annotations, such as:
Derived Annotation Name | Explain |
---|---|
ConditionalOnWebApplication | The current project is a Web project |
ConditionalOnJava | Java Version Based |
ConditionalOnJndi | Existence based on JNDI |
ConditionalOnWarDeployment | When an application is deployed for a traditional WAR |
ConditionalOnSingleCandidate | When a specified Bean is only one in a container, or if there are more than one but a preferred Bean is specified |
ConditionalOnProperty | Does the specified property have a specified value |
Profile | The specified Profile is activated |
ConditionalOnMissingBean | When no Bean is specified in the container |
ConditionalOnCloudPlatform | When a specified cloud platform is active |
ConditionalOnClass | When there is a specified class under the class path |
ConditionalOnMissingClass | When no class is specified under the class path |
ConditionalOnResource | Does the class path have a specified value |
ConditionalOnRepositoryType | Specific types of Spring data warehouses enabled |
ConditionalOnNotWebApplication | The current project is not a Web project |
ConditionalOnBean | When there is a specified Bean in the container |
ConditionalOnDefaultWebSecurity | Web Security is available and the user does not have a custom configuration |
ConditionalOnEnabledResourceChain | Check that the Spring resource processing chain is enabled. Matches whether WebProperties.Resources.Chain.getEnabled() is true, or whether webjar-locator-core is on the class path |
ConditionalOnExpression | Based on SpEL expression |
Example (ConditionalOnBean, adding user01 to container when pet03 exists)
MyConfig03.java
package cn.com.springboot.demo.config; import cn.com.springboot.demo.bean.Pet; import cn.com.springboot.demo.bean.User; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * The third configuration class example. * * Demo@Conditional * @author J */ @Configuration public class MyConfig03 { /** * Declare a component with ID user03. * Add user01 to container when pet03 exists */ @ConditionalOnBean(name = "pet01") @Bean public User user03() { return new User("Zhang San", "27"); } /** * Declare a component with an ID of pet. */ @Bean("pet") public Pet pet03() { return new Pet("cat", "coco"); } }
MainApp.java
package cn.com.springboot.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApp { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args); // Test MyConfig03's @ConditionalOnBean System.out.println(run.containsBean("user03")); } }
Run Results
false
- @ConditionalOnBean(name = "pet01") can be added to methods or classes
- Method: When the condition is not satisfied, only the current method will not be registered
- Class: When the condition is not satisfied, components in the entire class will not be registered
2.1.4. @ImportResource
Import a native configuration file. If there was a previous way to configure components using XML or a third-party way to configure components using XML, you need to import such configurations into your project. For example:
Example
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <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="user04" class="cn.com.springboot.demo.bean.User"> <property name="name" value="Zhang San" /> <property name="age" value="21" /> </bean> <bean id="pet04" class="cn.com.springboot.demo.bean.Pet"> <property name="breed" value="cat" /> <property name="petName" value="colina" /> </bean> </beans>
Myconfig04.java
package cn.com.springboot.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; /** * The fourth configuration class example. * * Demo@ImportResource * @author J */ @Configuration @ImportResource("classpath:beans.xml") public class MyConfig04 {}
MainApp.java
package cn.com.springboot.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApp { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApp.class, args); // Test @ImportResources for MyConfig04 System.out.println(run.containsBean("user04")); System.out.println(run.containsBean("pet04")); } }
Run Results
true true
2.1.5. @ConfigurationProperties
Configure bindings. In development, it is common to write changes in properties files, such as DB connection information.
2.1.5.1. @Component + @ConfigurationProperties
Example
Car.java
package cn.com.springboot.demo.bean; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * Vehicle information. * * @author J */ @Setter @Getter @ToString @NoArgsConstructor @Component @ConfigurationProperties("car01") public class Car { /** brand */ private String brand; /** Price */ private String price; public Car(String brand, String price) { this.brand = brand; this.price = price; } }
application.properties
car01.brand=BMW car01.price=1200000
CarController.java
package cn.com.springboot.demo.controller; import cn.com.springboot.demo.bean.Car; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CarController { @Autowired private Car car; @RequestMapping("/car") public Car myCar() { return car; } }
Run Results
- @Component: Register Car as a component to have the functionality provided by spring-boot
- @ConfigurationProperties: Specify the prefix of the configuration file
2.1.5.1. @ConfigurationProperties
Example
Car.java
package cn.com.springboot.demo.bean; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import org.springframework.boot.context.properties.ConfigurationProperties; /** * Vehicle information. * * @author J */ @Setter @Getter @ToString @NoArgsConstructor // @Component @ConfigurationProperties("car02") public class Car { /** brand */ private String brand; /** Price */ private String price; public Car(String brand, String price) { this.brand = brand; this.price = price; } }
application.properties
car02.brand=LEXUS car02.price=1800000
CarController.java
package cn.com.springboot.demo.controller; import cn.com.springboot.demo.bean.Car; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CarController { @Autowired private Car car; @RequestMapping("/car") public Car myCar() { return car; } }
MyConfig05.java
package cn.com.springboot.demo.config; import cn.com.springboot.demo.bean.Car; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * The fifth configuration class example. * * Demo @EnableConfiguration Properties * @author J */ @Configuration @EnableConfigurationProperties(Car.class) public class MyConfig05 {}
Run Results
- @ConfigurationProperties: Specify the prefix of the configuration file
- @EnableConfigurationProperties(${value}):
- Turn on configuration binding for specified ${value}
- Register the ${value} component into the container
- Must be written on configuration class