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:
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:
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,
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:
same as the first knowledge point, an error was reported that the bean was not found, then we printed out all the beanNames and
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
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.
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
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
- Is Spring IOC thread safe?
- The difference between @Service and @Component
@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