作者简介:zhz小白
公众号:小白的Java进阶之路
专业技能:
1、Java基础,并精通多线程的开发,熟悉JVM原理
2、熟悉Java基础,并精通多线程的开发,熟悉JVM原理,具备⼀定的线上调优经验
3、熟悉MySQL数据库调优,索引原理等,⽇志原理等,并且有出过⼀篇专栏
4、了解计算机⽹络,对TCP协议,滑动窗⼝原理等有⼀定了解
5、熟悉Spring,Spring MVC,Mybatis,阅读过部分Spring源码
6、熟悉SpringCloud Alibaba体系,阅读过Nacos,Sentinel,Seata,Dubbo,Feign,Gateway核⼼源码与设计,⼆次开发能⼒
7、熟悉消息队列(Kafka,RocketMQ)的原理与设计
8、熟悉分库分表ShardingSphere,具有真实⽣产的数据迁移经验
9、熟悉分布式缓存中间件Redis,对其的核⼼数据结构,部署架构,⾼并发问题解决⽅案有⼀定的积累
10、熟悉常⽤设计模式,并运⽤于实践⼯作中
11、了解ElasticSearch,对其核⼼的原理有⼀定的了解
12、了解K8s,Jekins,GitLab
13、了解VUE,GO
14、⽬前有正在利⽤闲暇时间做互游游戏,开发、运维、运营、推销等
本人著作git项目:https://gitee.com/zhouzhz/star-jersey-platform,有兴趣的可以私聊博主一起编写,或者给颗star
领域:对支付(FMS,FUND,PAY),订单(OMS),出行行业等有相关的开发领域
如果此文还不错的话,还请关注、点赞、收藏三连支持一下博主~
日常工作中,我们可以把一些bean组件通过包扫描+注解(@Controller,@Service,@Respository,@Component)的形式将入注入到IOC容器中,可以定制为单例Bean或者多例Bean,当然这种方式,一般局限于我们自己写的类。
如果是三方的类,我们一般怎么注入到容器中呢,有两种方方式:@Bean,@Import可以将其注入Spring容器中。
包扫描+注解(@Controller、@Servcie、@Repository、@Component)
@Bean注解,通常用于导入第三方包中的组件
@Import注解,快速向Spring容器中导入一个组件
接下来让我们开始走进@Import的世界,先看其源码:
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates one or more component classes to import — typically
* {@link Configuration @Configuration} classes.
*
* Provides functionality equivalent to the {@code } element in Spring XML.
* Allows for importing {@code @Configuration} classes, {@link ImportSelector} and
* {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component
* classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).
*
*
{@code @Bean} definitions declared in imported {@code @Configuration} classes should be
* accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
* injection. Either the bean itself can be autowired, or the configuration class instance
* declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly
* navigation between {@code @Configuration} class methods.
*
*
May be declared at the class level or as a meta-annotation.
*
*
If XML or other non-{@code @Configuration} bean definition resources need to be
* imported, use the {@link ImportResource @ImportResource} annotation instead.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.0
* @see Configuration
* @see ImportSelector
* @see ImportBeanDefinitionRegistrar
* @see ImportResource
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
我们从其中源码可以看出@Import是可以与@Configuration、ImportSelector、ImportBeanDefinitionRegistrar配合使用,并且可以看出其只能放到类上,不能放到方法或者属性上。
使用方式:
我们新建一个类叫White(空类),我们并未通过MainConfig进行注入,代码如下:
package com.zhz.bean;
/**
* @author zhouhengzhe
* @date 2022/11/15
*/
public class White {
}
我们可以发现一个现状,他没有把White类注入到Spring容器中,也就是说没有这个Bean实例。
然后我们简单使用下@Import,看一下演示效果,我们在MainConfig中添加一个@Import(White.class)去看一下效果,代码如下
package com.zhz.config;
import com.zhz.bean.Person;
import com.zhz.bean.White;
import com.zhz.condition.AppleCondition;
import com.zhz.condition.BananaCondition;
import com.zhz.condition.WatermelonCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:27
* @since v1
*/
@Configuration
@Import(White.class)
public class MainConfig {
@Bean(name = "person")
public Person person() {
return new Person("apple", 20);
}
/**
* @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
*/
@Bean(name = "apple")
@Conditional(AppleCondition.class)
public Person apple() {
return new Person("apple", 20);
}
@Bean(name = "banana")
@Conditional(BananaCondition.class)
public Person banana() {
return new Person("banana", 20);
}
@Bean(name = "watermelon")
@Conditional(WatermelonCondition.class)
public Person watermelon() {
return new Person("watermelon", 20);
}
}
然后我们运行一下test类,代码如下
@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
我们在创建一个Bean类,来验证批量导入,代码如下:
package com.zhz.bean;
/**
* @author zhouhengzhe
* @date 2022/11/15
*/
public class Blue {
}
在MainConfig中通过**@Import**注入,如下:
package com.zhz.test;
import com.zhz.bean.Person;
import com.zhz.config.MainConfig;
import com.zhz.scope.ThreadScope;
import org.junit.Test;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.concurrent.TimeUnit;
/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:58
* @since v1
*/
public class IOCTest {
@SuppressWarnings("resource")
@Test
public void test() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
// Person person1 = applicationContext.getBean(Person.class);
// System.out.println(person == person1);
}
@Test
public void test1() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
// 向容器中注册自定义的Scope
beanFactory.registerScope(ThreadScope.THREAD_SCOPE, new ThreadScope());
for (int i = 0; i < 2; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + ","+applicationContext.getBean("person"));
System.out.println(Thread.currentThread().getName() + ","+applicationContext.getBean("person"));
}).start();
}
try {
TimeUnit.SECONDS.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void test2(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// 我们现在就来看一下IOC容器中Person这种类型的bean都有哪些
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println(name);
}
}
@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
我们写一个test方法,来看一下Spring容器中的类,代码如下:
@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
首先我们先看一下ImportSelector接口的源码,我们可以发现其是导入外部配置的核心接口,在SpringBoot的自动装配和@Enable(XXX)都会有用到这个接口。代码如下:
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.util.function.Predicate;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.lang.Nullable;
/**
* Interface to be implemented by types that determine which @{@link Configuration}
* class(es) should be imported based on a given selection criteria, usually one or
* more annotation attributes.
*
* An {@link ImportSelector} may implement any of the following
* {@link org.springframework.beans.factory.Aware Aware} interfaces,
* and their respective methods will be called prior to {@link #selectImports}:
*
* - {@link org.springframework.context.EnvironmentAware EnvironmentAware}
* - {@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
* - {@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
* - {@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
*
*
* Alternatively, the class may provide a single constructor with one or more of
* the following supported parameter types:
*
* - {@link org.springframework.core.env.Environment Environment}
* - {@link org.springframework.beans.factory.BeanFactory BeanFactory}
* - {@link java.lang.ClassLoader ClassLoader}
* - {@link org.springframework.core.io.ResourceLoader ResourceLoader}
*
*
* {@code ImportSelector} implementations are usually processed in the same way
* as regular {@code @Import} annotations, however, it is also possible to defer
* selection of imports until all {@code @Configuration} classes have been processed
* (see {@link DeferredImportSelector} for details).
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see DeferredImportSelector
* @see Import
* @see ImportBeanDefinitionRegistrar
* @see Configuration
*/
public interface ImportSelector {
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
* @return the class names, or an empty array if none
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
/**
* Return a predicate for excluding classes from the import candidates, to be
* transitively applied to all classes found through this selector's imports.
* If this predicate returns {@code true} for a given fully-qualified
* class name, said class will not be considered as an imported configuration
* class, bypassing class file loading as well as metadata introspection.
* @return the filter predicate for fully-qualified candidate class names
* of transitively imported configuration classes, or {@code null} if none
* @since 5.2.4
* 返回用于从导入候选对象中排除类的谓词,为。
*可传递地应用于通过此选择器的导入找到的所有类。
*
如果此谓词返回给定完全限定的。
*类名,所述类不会被视为导入的配置类,绕过类文件加载以及元数据自省。
*@返回 完全限定候选类名的筛选器谓词,在传递导入的配置类中,
*/
@Nullable
default Predicate<String> getExclusionFilter() {
return null;
}
}
package com.zhz.selecter;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* 自定义逻辑,返回需要导入的组件
* @author zhouhengzhe
* @date 2022/11/16
*/
public class TestImportSelector implements ImportSelector {
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*
* @param importingClassMetadata 当前标注@Import注解的类的所有注解信息,也就是说不仅能获取到@Import注解里面的信息,还能获取到其他注解的信息
* @return 导入到容器中的组件的全类名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return null;
}
}
package com.zhz.config;
import com.zhz.bean.Blue;
import com.zhz.bean.Person;
import com.zhz.bean.White;
import com.zhz.condition.AppleCondition;
import com.zhz.condition.BananaCondition;
import com.zhz.condition.WatermelonCondition;
import com.zhz.selecter.TestImportSelector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:27
* @since v1
*/
@Configuration
@Import(value = {White.class, Blue.class, TestImportSelector.class})
public class MainConfig {
@Bean(name = "person")
public Person person() {
return new Person("apple", 20);
}
/**
* @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
*/
@Bean(name = "apple")
@Conditional(AppleCondition.class)
public Person apple() {
return new Person("apple", 20);
}
@Bean(name = "banana")
@Conditional(BananaCondition.class)
public Person banana() {
return new Person("banana", 20);
}
@Bean(name = "watermelon")
@Conditional(WatermelonCondition.class)
public Person watermelon() {
return new Person("watermelon", 20);
}
}
@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
然后我们进入asSourceClasses()方法,然后它里面有一行拿了当前上一行的返回值,而上一行的返回值是null,那么null.length()自然而然就会空指针了。
我们把继承了ImportSelector的TestImportSelector类的selectImports()改造一下返回值,返回一个空数组,代码如下:
然后我们再运行下面的test方法,代码如下
@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
修改MainConfig,代码如下:
package com.zhz.config;
import com.zhz.bean.Blue;
import com.zhz.bean.Person;
import com.zhz.bean.White;
import com.zhz.condition.AppleCondition;
import com.zhz.condition.BananaCondition;
import com.zhz.condition.WatermelonCondition;
import com.zhz.selecter.TestImportSelector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:27
* @since v1
*/
@Configuration
@Import(value = {TestImportSelector.class})
public class MainConfig {
@Bean(name = "person")
public Person person() {
return new Person("apple", 20);
}
/**
* @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
*/
@Bean(name = "apple")
@Conditional(AppleCondition.class)
public Person apple() {
return new Person("apple", 20);
}
@Bean(name = "banana")
@Conditional(BananaCondition.class)
public Person banana() {
return new Person("banana", 20);
}
@Bean(name = "watermelon")
@Conditional(WatermelonCondition.class)
public Person watermelon() {
return new Person("watermelon", 20);
}
}
然后我们改造一下TestImportSelector的selectImports()方法,代码如下:
package com.zhz.selecter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* 自定义逻辑,返回需要导入的组件
* @author zhouhengzhe
* @date 2022/11/16
*/
public class TestImportSelector implements ImportSelector {
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*
* @param importingClassMetadata 当前标注@Import注解的类的所有注解信息,也就是说不仅能获取到@Import注解里面的信息,还能获取到其他注解的信息
* @return 导入到容器中的组件的全类名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
/**
* 1、方法不要返回null值,否则会报空指针异常
* 2、可以返回一个空数组
*/
return new String[]{"com.zhz.bean.Blue","com.zhz.bean.White"};
}
}
然后运行test方法,代码如下:
@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
首先我们先看其源码,代码如下
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.type.AnnotationMetadata;
/**
* Interface to be implemented by types that register additional bean definitions when
* processing @{@link Configuration} classes. Useful when operating at the bean definition
* level (as opposed to {@code @Bean} method/instance level) is desired or necessary.
*
* Along with {@code @Configuration} and {@link ImportSelector}, classes of this type
* may be provided to the @{@link Import} annotation (or may also be returned from an
* {@code ImportSelector}).
*
*
An {@link ImportBeanDefinitionRegistrar} may implement any of the following
* {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective
* methods will be called prior to {@link #registerBeanDefinitions}:
*
* - {@link org.springframework.context.EnvironmentAware EnvironmentAware}
* - {@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
*
- {@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
*
- {@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
*
*
* Alternatively, the class may provide a single constructor with one or more of
* the following supported parameter types:
*
* - {@link org.springframework.core.env.Environment Environment}
* - {@link org.springframework.beans.factory.BeanFactory BeanFactory}
* - {@link java.lang.ClassLoader ClassLoader}
* - {@link org.springframework.core.io.ResourceLoader ResourceLoader}
*
*
* See implementations and associated unit tests for usage examples.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see Import
* @see ImportSelector
* @see Configuration
*/
public interface ImportBeanDefinitionRegistrar {
/**
* Register bean definitions as necessary based on the given annotation metadata of
* the importing {@code @Configuration} class.
* Note that {@link BeanDefinitionRegistryPostProcessor} types may not be
* registered here, due to lifecycle constraints related to {@code @Configuration}
* class processing.
*
The default implementation delegates to
* {@link #registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry)}.
* @param importingClassMetadata annotation metadata of the importing class
* @param registry current bean definition registry
* @param importBeanNameGenerator the bean name generator strategy for imported beans:
* {@link ConfigurationClassPostProcessor#IMPORT_BEAN_NAME_GENERATOR} by default, or a
* user-provided one if {@link ConfigurationClassPostProcessor#setBeanNameGenerator}
* has been set. In the latter case, the passed-in strategy will be the same used for
* component scanning in the containing application context (otherwise, the default
* component-scan naming strategy is {@link AnnotationBeanNameGenerator#INSTANCE}).
* @since 5.2
* @see ConfigurationClassPostProcessor#IMPORT_BEAN_NAME_GENERATOR
* @see ConfigurationClassPostProcessor#setBeanNameGenerator
*/
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
/**
* Register bean definitions as necessary based on the given annotation metadata of
* the importing {@code @Configuration} class.
* Note that {@link BeanDefinitionRegistryPostProcessor} types may not be
* registered here, due to lifecycle constraints related to {@code @Configuration}
* class processing.
*
The default implementation is empty.
* @param importingClassMetadata annotation metadata of the importing class
* @param registry current bean definition registry
*
* 向Spring容器中注册bean实例
*/
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
ImportBeanDefinitionRegistrar需要配合@Configuration和@Import这俩注解,其中,@Configuration注解定义Java格式的Spring配置文件,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类。
1、创建一个ImportBeanDefinitionRegistrar的实现类,空实现方法registerBeanDefinitions()
package com.zhz.registrar;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author zhouhengzhe
* @date 2022/11/16
*/
public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
*
* 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
2、接着我们在MainConfig中用@Import把他添加进去
package com.zhz.config;
import com.zhz.bean.Person;
import com.zhz.condition.AppleCondition;
import com.zhz.condition.BananaCondition;
import com.zhz.condition.WatermelonCondition;
import com.zhz.registrar.TestImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:27
* @since v1
*/
@Configuration
@Import(value = {TestImportBeanDefinitionRegistrar.class})
public class MainConfig {
@Bean(name = "person")
public Person person() {
return new Person("apple", 20);
}
/**
* @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
*/
@Bean(name = "apple")
@Conditional(AppleCondition.class)
public Person apple() {
return new Person("apple", 20);
}
@Bean(name = "banana")
@Conditional(BananaCondition.class)
public Person banana() {
return new Person("banana", 20);
}
@Bean(name = "watermelon")
@Conditional(WatermelonCondition.class)
public Person watermelon() {
return new Person("watermelon", 20);
}
}
4、接着我们把registerBeanDefinitions()方法定制一下自己的逻辑
package com.zhz.registrar;
import com.zhz.bean.Blue;
import com.zhz.bean.White;
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;
/**
* @author zhouhengzhe
* @date 2022/11/16
*/
public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
*
* 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinitionBlue = new RootBeanDefinition(Blue.class);
RootBeanDefinition rootBeanDefinitionWhite = new RootBeanDefinition(White.class);
registry.registerBeanDefinition("blue",rootBeanDefinitionBlue);
registry.registerBeanDefinition("white",rootBeanDefinitionWhite);
}
}
package com.zhz.registrar;
import com.zhz.bean.Blue;
import com.zhz.bean.White;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author zhouhengzhe
* @date 2022/11/16
*/
public class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
*
* 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean
*/
// @Override
// public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// RootBeanDefinition rootBeanDefinitionBlue = new RootBeanDefinition(Blue.class);
// RootBeanDefinition rootBeanDefinitionWhite = new RootBeanDefinition(White.class);
//
// registry.registerBeanDefinition("blue",rootBeanDefinitionBlue);
// registry.registerBeanDefinition("white",rootBeanDefinitionWhite);
//
// }
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
RootBeanDefinition rootBeanDefinitionBlue = new RootBeanDefinition(Blue.class);
RootBeanDefinition rootBeanDefinitionWhite = new RootBeanDefinition(White.class);
registry.registerBeanDefinition(importBeanNameGenerator.generateBeanName(rootBeanDefinitionBlue,registry),rootBeanDefinitionBlue);
registry.registerBeanDefinition(importBeanNameGenerator.generateBeanName(rootBeanDefinitionWhite,registry),rootBeanDefinitionWhite); }
}