【Spring【IOC】】——7


在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);
}
}


最后我们看一下运行结果:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7fafd39e2e8c43b29da58a2e28b59f13.png)


* **我们可以发现通过@Import注解,是可以同时导入多个Bean到Spring容器中。**


#### 5.2.2、ImportSelector,即批量导入(重点)


首先我们先看一下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 getExclusionFilter() {
return null;
}

}


* 主要作用是收集需要导入的配置类,selectImports()方法的返回值就是我们向Spring容器中导入的类的全类名。如果该接口的实现类同时实现EnvironmentAware,BeanFactoryAware,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其selectImports()方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完再导入时,那么可以实现DeferredImportSelector接口。
* 在ImportSelector接口的selectImports()方法中,存在一个AnnotationMetadata类型的参数,这个参数能够获取到当前标注@Import注解的类的所有注解信息,也就是说不仅能获取到@Import注解里面的信息,还能获取到其他注解的信息


##### 5.2.2.1、上实践用例


###### 5.2.2.1.1、首先我们创建一个类它实现了ImportSelector接口,代码如下:



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;
}
}


###### 5.2.2.1.2、我们在MainConfig中通过@Import引入该类,代码如下:



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);
}

}


###### 5.2.2.1.3、我们在TestImportSelector类上的selectImports()方法增加一个断点,然后我们dubug下面的测试方法


![在这里插入图片描述](https://img-blog.csdnimg.cn/84715cc0e8184c069d0eeb792a1e1c1b.png)



@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}


###### 5.2.2.1.4、我们dubug之后发现,打到这个断点之前,是没有任何输出的,说明是在bean实例化前就做了,如下


![在这里插入图片描述](https://img-blog.csdnimg.cn/3dfb4277334e480cac7d872d5b70ddd9.png)


###### 5.2.2.1.5、然后我们再回归selectImports()方法,看一下他的参数的值,可以发现他获取到了当前标注了@Import注解的类的所有注解信息。


![在这里插入图片描述](https://img-blog.csdnimg.cn/2a1bb5ebe0fc4628bf0dce596f9a475c.png)


我们发现执行到下一步的时候有个空指针异常,如下  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3d921d2be55a416bb08775e0998d0640.png)


控制台输出也是空指针异常。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/928516b5a8b84c99a67620fc715c52c6.png)


###### 5.2.2.1.6、我们来研究一下为什么会空指针?


继续打开dubug,我们可以发现它后面执行到了,如下:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/27d8fab7577d46e99a39d7ccbeab3c1e.png)


然后我们进入asSourceClasses()方法,然后它里面有一行拿了当前上一行的返回值,而上一行的返回值是null,那么null.length()自然而然就会空指针了。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c7f153eeb8204481b1d1f703cb104d0f.png)


###### 5.2.2.1.7、防止以上空指针,代码改造


我们把继承了ImportSelector的TestImportSelector类的selectImports()改造一下返回值,返回一个空数组,代码如下:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/a5e3c2c247d14ccd86004a3dd33081cb.png)


然后我们再运行下面的test方法,代码如下



@Test
public void test3(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}


运行结果为:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/801fce118e1e4979b2e9051a35b05f31.png)


* 因为我们的selectImports()方法返回为一个空数组,所以自然而然就没有通过ImportSelector接口的方式注册的Bean的全类名集合输出了。


###### 5.2.2.1.8、改造White.class,blue.class的导入方式


修改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);
    }
}

运行结果如下:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d0521efcbd7043c481c50ed1ada22e8b.png)


* **因此,我们是不是可以发现Blue,White两个类也注入进来了**


#### 5.2.3、ImportBeanDefinitionRegistrar接口方式,即手工注册bean到容器中


##### 5.2.3.1、ImportBeanDefinitionRegistrar介绍


首先我们先看其源码,代码如下



/*
* 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本质上是一个接口。在ImportBeanDefinitionRegistrar接口中,有一个registerBeanDefinitions()方法,通过该方法,我们可以向Spring容器中注册bean实例。
* Spring在动态注册Bean的时候,都是采用这个ImportBeanDefinitionRegistrar接口,
* 所有实现了该接口的类都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化的,也能被aop、validator等机制处理。


##### 5.2.3.2、使用方法


ImportBeanDefinitionRegistrar需要配合@Configuration和@Import这俩注解,其中,@Configuration注解定义Java格式的Spring配置文件,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类。


##### 5.2.3.3、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);
}

}


3、然后我们运行下test方法,看一下效果  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/40523685b8514484b4a04b32829f05fc.png)


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);

}

}


然后我们运行一下test方法,看一下效果  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0819b898681c4b24872644e1056c81a3.png)


* 是不是发现了Blue,White被注入到Spring容器中了,并且命名还是我们自己命的,当然我们也可以让Spring自己生成,换一个父类方法就可以嘞,他注册的Bean名字是全类名



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);

独家面经总结,超级精彩

本人面试腾讯,阿里,百度等企业总结下来的面试经历,都是真实的,分享给大家!

image

image

image

image

Java面试准备

准确的说这里又分为两部分:

  1. Java刷题
  2. 算法刷题

Java刷题:此份文档详细记录了千道面试题与详解;

image

image

onRegistrar {
/**
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
*


* 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean
*/
// @Override
// public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// RootBeanDefinition rootBeanDefinitionBlue = new RootBeanDefinition(Blue.class);

独家面经总结,超级精彩

本人面试腾讯,阿里,百度等企业总结下来的面试经历,都是真实的,分享给大家!

[外链图片转存中…(img-1crxvlu8-1718783589558)]

[外链图片转存中…(img-brR0hYVq-1718783589559)]

[外链图片转存中…(img-8sXWV2my-1718783589560)]

[外链图片转存中…(img-ahxOt471-1718783589561)]

Java面试准备

准确的说这里又分为两部分:

  1. Java刷题
  2. 算法刷题

Java刷题:此份文档详细记录了千道面试题与详解;

[外链图片转存中…(img-FZmSJtQT-1718783589561)]

[外链图片转存中…(img-WeO4FxN0-1718783589562)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值