Hello everyone, I am xiao CAI, a desire to do CAI Not CAI xiao CAI in the Internet industry. Soft but just, soft praise, white piao just! Ghost ~ remember to give me a three – even oh!


This article focuses on the annotation development of IOC in Spring

Refer to it if necessary

If it is helpful, do not forget the Sunday

Creation is not easy, white piao no righteousness!

Previously:

XML configuration injection class:

  • Create a class to inject

  • Create a Spring configuration file

  • Then register with

Annotation-based injection:

  • Write a Person class:
public class Person {
 private String name;
 private Integer age;
 // omit the get/set method
}
Copy the code
  • Write a configuration class:
// Config class == config file
@Configuration  // Tell Spring that this is a configuration class
public class MainConfig {
 // Register a Bean in the container; Type is the type of the return value. Id defaults to the method name as id
 // The ID can also be specified by @bean (value)
 @Bean("person")  public Person person01(a){  return new Person("Cbuc".22);  } } Copy the code
  • Write a test class:
public void test01(a){
    / / can notice before based on XML is new ClassPathXmlApplicationContext (), based on annotations are now new AnnotationConfigApplicationContext ()
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    Person person = (Person) applicationContext.getBean("person");
    System.out.println(person);
} Copy the code

The injected class was successfully obtained:


Steps,

1) Packet scanning

XML scan mode: You can configure filtering conditions

<context:component-scan base-package="cbuc.lie" use-default-filters="false"></context:component-scan>
Copy the code

Note scanning :(@componentscan)

/ * * * @ComponentScanValue: specifies the packets to be scanned* excludeFilters = Filter[] : Specify what rules to exclude components when scanning* includeFilters = Filter[] : specifies which components to include when scanning* FilterType.ANNOTATION: Follow the ANNOTATION* filtertype. ASSIGNABLE_TYPE: according to the given type;* filterType.aspectj: Uses ASPECTJ expressions* filterType. REGEX: Specifies with a re* filterType. CUSTOM: Use CUSTOM rules* /  // Config class == config file @ Configuration // Tell Spring that this is a configuration class @ ComponentScans( / / componentScan combination  value = {  @ ComponentScan(value="cbuc.life.bean",includeFilters = {  @Filter(type=FilterType.ANNOTATION,classes={Component.class})  /* @Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),  @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}) */  },  useDefaultFilters = false)  } ) public class MainConfig {  // Register a Bean in the container; Type is the type of the return value. Id defaults to the method name as id  @Bean("person")  public Person person01(a){  return new Person("Cbuc".22);  } } Copy the code

– FilterType.CUSTOM is used

  1. Define an implementation class of TypeFilter, MyTypeFilter
public class MyTypeFilter implements TypeFilter {
 / * ** metadataReader: Read information about the currently being scanned class* metadataReaderFactory: Can get information about any other class* /
 public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)  throws IOException {  // Get information about the current class annotation  AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();  // Get the class information for the class currently being scanned  ClassMetadata classMetadata = metadataReader.getClassMetadata();  // Get the current class resource (class path)  Resource resource = metadataReader.getResource();   String className = classMetadata.getClassName();  System.out.println("- >"+className);  if(className.contains("er")) {// Pass the class whose class name contains "er"  return true;  }  return false;  } } Copy the code
  1. through@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}Just introduce it in classes

2) Scope

Adjust Scope via @scope (singleton by default)

  • Singleton: single-instance (default). The IOC container start calls methods to create objects to be placed in the IOC container. ***map.get()***

  • Request: Creates an instance for the same request

  • Session: Creates an instance of the same session

3) Lazy loading

* Single-instance beans: * Objects are created by default when the container is started;

* Lazy loading: * Containers start without creating objects. The first time an object is created and initialized using a (get)Bean;


4) Conditional injection@Conditional({Condition})

  1. Write the implementation class of Condition, WindowsCondition
// Check whether the current environment is Windows
public class WindowsCondition implements Condition {
 public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  Environment environment = context.getEnvironment();
  String property = environment.getProperty("os.name");
 if(property.contains("Windows")) { return true;  }  return false;  } } Copy the code
  1. Inject beans based on conditions
  1. We can place @Conditional annotations on methods as well as on classes (with higher priority than methods)

5) Import a component into the container@Import

To register a component in a container:

  1. Package scan + Component annotation (@controller / @service / @repository /@Component)

  2. The config class is registered via @bean

  3. @import (quickly Import a component into a container)

    • 1) @import (components to be imported into containers); The component is automatically registered in the container, and the id defaults to the full class name


    • 2) ImportSelector: Returns an array of the full class names of the components to be imported

      Write an implementation class for ImportSelector

      public class MyImportSelector implements ImportSelector {
       // The return value is the full class name of the component imported into the container
       AnnotationMetadata: all annotation information for the class currently annotated with @import annotations
       public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // TODO Auto-generated method stub
       //importingClassMetadata  // methods do not return null values  return new String[]{"cbuc.life.bean.Blue"."cbuc.life.bean.Yellow"};  } } Copy the code

      Declare it in @import


    • 3) ImportBeanDefinitionRegistrar: manually register beans into the container

      Writing ImportBeanDefinitionRegistrar implementation class

      public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
       / * ** AnnotationMetadata: Annotation information for the current class* BeanDefinitionRegistry: BeanDefinition registered classes;* Add all beans that need to be added to the container; call* BeanDefinitionRegistry registerBeanDefinition manual registration* /  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {  boolean definition = registry.containsBeanDefinition("Red");  boolean definition2 = registry.containsBeanDefinition("Blue");  if(definition && definition2){ // Register the RainBow class if the IOC container contains Red and Blue  // Specify the Bean definition information; (Type of Bean, Bean...)  RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);  // Register a Bean and specify the Bean name  registry.registerBeanDefinition("rainBow", beanDefinition);  }  } } Copy the code

      Declare it in @import


6) FactoryBean

1) The default is to get the object created by the factory bean calling getObject

2) To get the factory Bean itself, we need to add &ColorFactoryBean in front of the ID

  1. Write the FactoryBean implementation class:
// Create a Spring-defined FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
 // Returns a Color object, which is added to the container
 public Color getObject(a) throws Exception {
  System.out.println("ColorFactoryBean... getObject...");
 return new Color();  }  publicClass<? > getObjectType() { return Color.class;  }  // Is it a singleton?  //true: This bean is singleton and holds a copy in the container  //false: multi-instance, each fetch creates a new bean;  public boolean isSingleton(a) {  return false;  } } Copy the code
  1. Register in the configuration class:
 @Bean
 public ColorFactoryBean colorFactoryBean(a){
  return new ColorFactoryBean();
 }
Copy the code
  1. Note:

The colorFactoryBean is injected, but the Color is retrievedIf you want to get the colorFactoryBean, you add an & before the ID

7) Life cycle

Bean life cycle:

Bean creation – initializes —- destruction process

Lifecycle of container-managed beans; We can customize initialization and destruction methods; The container calls our custom initialization and destruction methods at the end of the bean’s current life cycle

1) Specify initialization and destruction methods;

  • Specified by @beaninit-methodanddestroy-method

We create a Car class with custom initialization and destruction methods:

public class Car {
 public Car(a){
  System.out.println("car constructor...");
 }
 public void init(a){
 System.out.println("car ... init...");  }  public void detory(a){  System.out.println("car ... detory...");  } } Copy the code

Registering to an IOC container:

// Specify initialization and destruction methods in Bean annotations
@Bean(initMethod="init",destroyMethod="detory")
public Car car(a){
 return new Car();
}
Copy the code

2) By making the Bean implement

  • InitializingBean(Define initialization logic)
  • DisposableBean(Define destruction logic)

We create a Cat class that implements the InitializingBean and DisposableBean interfaces:

@Component  // Enable packet scanning in the configuration class to automatically register with the IOC container
public class Cat implements InitializingBean.DisposableBean {
 public Cat(a){
  System.out.println("cat constructor...");
 }
 public void afterPropertiesSet(a) throws Exception {  // Initialize method  System.out.println("cat... afterPropertiesSet...");  }  public void destroy(a) throws Exception {  // Destruction method  System.out.println("cat... destroy...");  } } Copy the code

3) Use JSR250

  • @PostConstructExecute the initialization method after the bean is created and the property assignment is complete
  • @PreDestroy: Notify us of the cleanup before the container destroys the bean

First create a Dog class:

@Component  // Enable packet scanning in the configuration class to automatically register with the IOC container
public class Dog {
 public Dog(a){
  System.out.println("dog constructor...");
 }
 // called after the object is created and assigned  @PostConstruct  public void init(a){  System.out.println("Dog.... @PostConstruct...");  }  // Before the container removes the object  @PreDestroy  public void detory(a){  System.out.println("Dog.... @PreDestroy...");  } } Copy the code

4) BeanPostProcessor [interface] : the post-processor of the bean

  • Do some processing before and after bean initialization;
  • postProcessBeforeInitialization: Works before initialization
  • postProcessAfterInitialization: Works after initialization

We create a MyBeanPostProcessor class that implements the BeanPostProcessor interface:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
 // Operations performed before initialization
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  System.out.println("postProcessBeforeInitialization..."+beanName+"= >"+bean);
 return bean;  }  // Operations performed after initialization  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  System.out.println("postProcessAfterInitialization..."+beanName+"= >"+bean);  return bean;  } } Copy the code

8) Parameter assignment

Assign with @value:

  1. The basic numerical

  2. SpEL: #{}

  3. You can write **${}** : fetch the value in the configuration file properties (the value in the runtime environment variable).

9) Automatic assembly

Spring uses dependency injection (DI) to assign dependencies to various components in the IOC container

@autoWired: Automatic injection


  1. The default is to find the corresponding component in the container by type:

ApplicationContext. GetBean (BookDao. Class) to find the assignment

  1. If multiple components of the same type are found, then use the property name as the component ID to find the container:

    applicationContext.getBean("bookDao")

  2. Instead of using attribute names, use @Qualifier to specify the ID of the component to be assembled

  1. By default, autowiring must assign a good value to the property, otherwise an error will be reported

    Empty assemblies can be allowed using @AutoWired (Required =false)

  1. use@PrimaryPreferred is used by default when you have Spring autowiring

You can also use @qualifier to specify the name of the bean to be assembled with a higher priority

Spring also supports @Resource(JSR250) and @Inject(JSR330).

  1. @ the Resource:

    • Can implement autowiring function like @autowired; The default is to assemble by component name;
    • Can’t support@PrimaryFunction and not supportedThe @autowired (reqiured = false)
  2. @Inject:

    • You need to importjavax.injectPackage, and **Autowired ** function the same. There is norequired=falseThe function;

@autoWired tag positions: constructor, parameter, method, attribute

Constructor: If the component has only one parameter constructor, the @autowired of the parameter constructor can be omitted, and the component at the parameter position can still be automatically fetched from the container

Parameter (@autowired can be omitted)

Method: @bean + method parameter; Parameters are taken from the container; If you don’t say @Autowired by default, it’s the same thing; It’s all self-assembly

Properties:

10) @profile specifies the environment

Spring provides the ability to dynamically activate and switch a range of components (development, test, production…) based on the current environment.

  • @profile: Specifies the context in which a component can be registered in the container. If not specified, it can be registered in any context

    1. A bean with an environment identifier that can only be registered with the container if the environment is active. The default is the default environment
    2. Write on the configuration class, only the specified environment, the entire configuration in the configuration class can take effect
    3. Beans that are not marked with an environment identity are loaded in any environment
  • Switch the environment

    1) Use command line dynamic parameters: load -dspring.profiles. active=test in the vm parameter location


    2) Code the way to activate an environment

// Create an applicationContext
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//2. Set the environment to be activated
applicationContext.getEnvironment().setActiveProfiles("dev");
//3. Register the master configuration class
applicationContext.register(MainConfigOfProfile.class); // Start the refresh container applicationContext.refresh(); Copy the code
They’re all bad guys

Today you work harder, tomorrow you will be able to say less words!

I am xiao CAI, a man who studies with you. 💋