咱们通常在项目开发中都是使用这种方式。java
通常导入第三方组件的时候使用,如注册一个RedisTemplate
:git
@Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); // 设置值(value)的序列化采用KryoRedisSerializer。 redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); // 设置键(key)的序列化采用StringRedisSerializer。 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; }
通常快速导入一批组件时使用,如同时注册好几个动物类:github
@Configuration @Import({DogTestBean.class, CatTestBean.class}) public class ImportConfig { @Bean public ImportTestBean importTestBean() { return new ImportTestBean(); } }
容器中的Bean:redis
打印 Spring 容器中的Bean 开始 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importConfig com.xiaolyuh.iimport.DogTestBean com.xiaolyuh.iimport.CatTestBean importTestBean 打印 Spring 容器中的Bean 结束
@Configuration @Import({DogTestBean.class, CatTestBean.class, AnimalImportSelector.class}) public class ImportConfig { @Bean public ImportTestBean importTestBean() { return new ImportTestBean(); } } public class AnimalImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 不能返回NULL,不然会报空指针异常,打断点能够看到源码 return new String[]{"com.xiaolyuh.iimport.bean.FishTestBean", "com.xiaolyuh.iimport.bean.TigerTestBean" }; } }
打印 Spring 容器中的Bean 开始 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importConfig com.xiaolyuh.iimport.bean.DogTestBean com.xiaolyuh.iimport.bean.CatTestBean com.xiaolyuh.iimport.bean.FishTestBean com.xiaolyuh.iimport.bean.TigerTestBean importTestBean 打印 Spring 容器中的Bean 结束
selectImports()
这个方法不能返回NULL,不然会报空指针异常,从源代码来看是在以下位置报出来的:springprivate Collection<SourceClass> asSourceClasses(String[] > classNames) throws IOException { List<SourceClass> annotatedClasses = new ArrayList<SourceClass>(classNames.length); for (String className : classNames) { annotatedClasses.add(asSourceClass(className)); } return annotatedClasses; }
只有动物园里面有 猫和狗的时候我么才将猪注入进去。ImportBeanDefinitionRegistrar注册器,在注册bean的过程当中会在最后执行。缓存
@Configuration @Import({DogTestBean.class, CatTestBean.class, AnimalImportSelector.class, AnimalImportBeanDefinitionRegistrar.class}) public class ImportConfig { @Bean public ImportTestBean importTestBean() { return new ImportTestBean(); } } public class AnimalImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * @param importingClassMetadata 当前类的注解信息 * @param registry 注册器,经过注册器将特定类注册到容器中 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 猫和狗的Bean咱们能够声明一个注解,相似Spring Boot的条件注解 boolean isContainsDog = registry.containsBeanDefinition(DogTestBean.class.getName()); boolean isContainsCat = registry.containsBeanDefinition(CatTestBean.class.getName()); if (isContainsDog && isContainsCat) { RootBeanDefinition beanDefinition = new RootBeanDefinition(PigTestBean.class); // 第一个参数是Bean id ,第二个是RootBeanDefinition registry.registerBeanDefinition("pigTestBean", beanDefinition); } } }
打印 Spring 容器中的Bean 开始 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importConfig com.xiaolyuh.iimport.bean.DogTestBean com.xiaolyuh.iimport.bean.CatTestBean com.xiaolyuh.iimport.bean.FishTestBean com.xiaolyuh.iimport.bean.TigerTestBean importTestBean pigTestBean 打印 Spring 容器中的Bean 结束
- 经过该方式注册Bean,必须将Bean封装成 RootBeanDefinition。
- ImportBeanDefinitionRegistrar注册器,在注册bean的过程当中会在最后执行。
- 跟进源码咱们能够看到容器就是一个Map,
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
@Configuration @Import({DogTestBean.class, CatTestBean.class, AnimalImportSelector.class, AnimalImportBeanDefinitionRegistrar.class}) public class ImportConfig { @Bean public ImportTestBean importTestBean() { return new ImportTestBean(); } // 最终注入的实际上是 MonkeyTestBean 类 @Bean public AnimalFactoryBean monkeyTestBean() { return new AnimalFactoryBean(); } } public class AnimalFactoryBean implements FactoryBean { /** * 获取实例 * * @return * @throws Exception */ @Override public MonkeyTestBean getObject() throws Exception { return new MonkeyTestBean(); } /** * 获取示例类型 * * @return */ @Override public Class<?> getObjectType() { return MonkeyTestBean.class; } /** * 是否单例 * * @return */ @Override public boolean isSingleton() { return true; } }
输出结果:框架
打印 Spring 容器中的Bean 开始 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importConfig com.xiaolyuh.iimport.bean.DogTestBean com.xiaolyuh.iimport.bean.CatTestBean com.xiaolyuh.iimport.bean.FishTestBean com.xiaolyuh.iimport.bean.TigerTestBean importTestBean monkeyTestBean pigTestBean 打印 Spring 容器中的Bean 结束 开始获取容器中的Bean 14:07:12.533 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'monkeyTestBean' MonkeyTestBean 初始化 14:07:12.534 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'monkeyTestBean' true 我爱吃香蕉
使用该方式会注册两个Bean到容器,一个是
FactoryBean
,一个是咱们真实须要注册的Bean,如demo中的MonkeyTestBean
。 使用该方式无论是不是单例模式下,实例化真实的Bean都是在第一次获取Bean 的时候。也就是说都是在容器初始化完成以后。 根据名称获取Bean的时候,若是在Bean名称前加一个&
符号表示获取工厂Bean,不然是获取咱们真实注册的Bean。ide
- ‘@Autowired’ 和‘@Inject’他们都是经过‘AutowiredAnnotationBeanPostProcessor’ 类实现的依赖注入,两者具备可互换性。
- ‘@Resource’经过 ‘CommonAnnotationBeanPostProcessor’ 类实现依赖注入,即使如此他们在依赖注入时的表现仍是极为相近的。
如下是他们在实现依赖注入时执行顺序的归纳:spring-boot
@Autowired and @Injectui
@Resource
https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases
spring-boot-student-spring 工程
为监控而生的多级缓存框架 layering-cache这是我开源的一个多级缓存框架的实现,若是有兴趣能够看一下