Spring5 source code analysis-basic knowledge understanding (two)

The code address
spring01
thinks that the blogger can also give a Star

1. The use
of @Import Create UserEntity.java under com.entity

package com.entity;
public class UserEntity {
    
    

}

Create MyConfig.java under com.config

package com.config;

import com.entity.UserEntity;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(UserEntity.class)
public class MyConfig {
    
    

}

Create Application.java under com

package com;

import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        UserEntity userEntity = applicationContext.getBean("userEntity", UserEntity.class);
        System.out.println(userEntity);
    }
}

The test code is as above, and the result of the operation:
Insert picture description here
we will find that our operation steps are similar to yesterday, but the error "No'UserEntity' object was found" will be reported. Next, we will print out all the injected bean names.

String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (int i = 0; i < beanDefinitionNames.length; i++) {
    
    
    System.out.println(beanDefinitionNames[i]);
}

Operation result:
Insert picture description here
We will find that its bean name is "com.entity.UserEntity". At this time, we can discover that, unlike the name we usually use to inject beans with annotations, the injected name is the full path, so our code should be changed for

UserEntity userEntity = applicationContext.getBean("com.entity.UserEntity", UserEntity.class);

There will be no problems with the results of this operation

2.@EnableXXX
We have seen a lot of annotations at the beginning of Enable, such as @EnableScheduling, @EnableAsync, etc., we can go in and take a look,
Insert picture description here
Insert picture description here
we can all see a very familiar figure @Import, yes , He is the core, mainly for importing external classes

3.FactoryBean
the FactoryBean indicates to the IOC storage container (target injection), BeanFactory retrieves the object from the IOC container

com.entity creates FactoryBeanEntity.java

package com.entity;
public class FactoryBeanEntity {
    
    
}

com.config creates FactoryBeanConfig.java and implements the interface FactoryBean

package com.config;

import com.entity.FactoryBeanEntity;
import org.springframework.beans.factory.FactoryBean;

public class FactoryBeanConfig implements FactoryBean<FactoryBeanEntity> {
    
    
    @Override
    public FactoryBeanEntity getObject() throws Exception {
    
    
        return new FactoryBeanEntity();
    }

    @Override
    public Class<?> getObjectType() {
    
    
        return FactoryBeanEntity.class;
    }

    @Override
    public boolean isSingleton() {
    
    
        // 是否为单例 true为单例 false 为多例
        return true;
    }
}

Add "FactoryBeanConfig.class" to @Import in MyConfig.java.
Let's test whether the injection is successful.
Application.java adds code

FactoryBeanEntity factoryBeanEntity = applicationContext.getBean("factoryBeanEntity", FactoryBeanEntity.class);
System.out.println(factoryBeanEntity);

Operation result:
Insert picture description here
same as the first knowledge point, an error was reported that the bean was not found, then we printed out all the beanNames and
Insert picture description here
found that we did not have "factoryBeanEntity" in it, but only "com.config.FactoryBeanConfig" appeared,
then we started from " com.config.FactoryBeanConfig" to find out, change the code

// 此处打断点
Object factoryBeanConfig = applicationContext.getBean("com.config.FactoryBeanConfig");
System.out.println(factoryBeanConfig);

We will find that
Insert picture description here
this is clear, the original injected name is "com.config.FactoryBeanConfig", and the corresponding object is "FactoryBeanEntity", then we can try to force the type directly

FactoryBeanEntity factoryBeanConfig = (FactoryBeanEntity)applicationContext.getBean("com.config.FactoryBeanConfig");
System.out.println(factoryBeanConfig);

The result is that it can be forced to FactoryBeanEntity, indicating that the FactoryBeanEntity injection is successful

4. The use of
@Conditional @Conditional is mainly used for conditional registration. For example, in different operating systems, we need to use different beans
to create ConditionConfig.java under com.config to implement the Condition interface

package com.config;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class ConditionConfig implements Condition {
    
    
    /**
     *
     * @param conditionContext 获取当前上下文
     * @param annotatedTypeMetadata 获取当前注解的信息
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
    
    
        // 获取当前系统环境
        Environment environment = conditionContext.getEnvironment();
        String osName = environment.getProperty("os.name");
        if(osName.equals("Windows 10")){
    
    
            // 注册
            return true;
        }
        // 不进行注册
        return false;
    }
}

com.entity creates Win10Entity.java

package com.entity;

public class Win10Entity {
    
    
}

MyConfig.java

package com.config;

import com.entity.UserEntity;
import com.entity.Win10Entity;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
//@EnableAsync
//@EnableScheduling
@Import({
    
    UserEntity.class,FactoryBeanConfig.class})
public class MyConfig {
    
    

    @Bean
    @Conditional(ConditionConfig.class)
    public Win10Entity win10Entity(){
    
    
        return new Win10Entity();
    }
}

Run and print all beanNames.
Insert picture description here
In this way, we can control the registration of objects in different environments through @Conditional

5.
ImportSelector interface uses ImportSelector to selectively register bean
com.entity to create Select01Entity.java

package com.entity;

public class Select01Entity {
    
    
}

com.config creates ImportSelectorConfig and implements the interface ImportSelector

package com.config;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class ImportSelectorConfig implements ImportSelector {
    
    
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    
    
        return new String[]{
    
    "com.entity.Select01Entity"};
    }
}

Print all the beanNames, you can find "com.entity.Select01Entity" injected successfully
Insert picture description here
5. ImportBeanDefinitionRegistrar uses the
com.config package to create ImportBeanDefinitionRegistrarConfig.java and implement the interface ImportBeanDefinitionRegistrar

package com.config;

import com.entity.SmsEntity;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;

public class ImportBeanDefinitionRegistrarConfig implements ImportBeanDefinitionRegistrar {
    
    
    /**
     * @param annotationMetadata 注解信息
     * @param beanDefinitionRegistry bean的基本信息
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
    
    
        // 手动注册信息到ioc
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(SmsEntity.class);
        beanDefinitionRegistry.registerBeanDefinition("smsEntity",rootBeanDefinition);
    }
}

Add ImportBeanDefinitionRegistrarConfig.class in @Import of MyConfig.java

Problem thinking

  1. Is Spring IOC thread safe?
  2. The difference between @Service and @Component

  3. @Primary and @Qualifier difference 1. SpringIOC thread safety, the bottom layer is stored through beanDefinitionMap
    2. The two annotations have the same bottom layer, only for better distinction when writing
    3. Both are used when there is an implementation class with one interface, @ Qualifier specifies the use of the implementation class, @Primary specifies that the two implementation classes prefer to use one of the implementation classes

Guess you like

Origin blog.csdn.net/weixin_43911969/article/details/113846033