spring容器注册组件的方式

给容器注册组件的方式:

1.包扫描+组件标注注解(@Controller @Servuce @Repostiory @Component) --局限自己写的类

1)配置文件的方式

在application.xml中配置,配置包扫描路径

<context:component-scan base-package="com.dingaimin"></context:component-scan>

在com.dingaimin包下的并使用 @Controller @Servuce @Repostiory @Component 注解的类会被加载到spring容器中。

也可以在配置文件中通过 <bean></bean>标签注入,注入方式有set方法注入,构造器注入,如下面的是set方法注入

<bean id="person" class="com.dingaimin.bean.Person">
        <property name="age" value="27"></property>
        <property name="name" value="dingaimin"></property>
</bean>

2)注解方式

首先创建一个配置类(相当于之前的配置文件),并使用

@Configuration 修饰类 让spring容器知道该类是个配置类

@ComponentScan 包扫描 可以配置排除和包含逻辑

   ①excludeFilters = Filter[] 指定扫描时排除哪些组件

   ②includeFilters = Filter[] 指定扫描时包含哪些组件,注意这里要让其生效,需要配置 useDefaultFilters = false

@Configuration
@ComponentScan(value = "com.dingaimin",includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BookService.class),
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})},useDefaultFilters = false)
public class MainConfig {

   
}

2.@Bean 导入第三方包里的组件

/**
     * 默认是单实例
     * @Scope
     *  prototype 多实例 ioc容器启动并不会去调用方法创建对象放到容器中,每次获取的时候才会调用方法创建对象
     *  singleton 单实例(默认) ioc容器启动会调用方法创建对象放到ioc容器中,后面的获取,直接从容器中拿
     *
     *  懒加载 单实例bean,容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化
     *
     * @Conditional 按照一定的条件进行判断,满足条件给容器中注册bean
     *
     * @return
     */
    @Scope("prototype")
    @Lazy
    @Bean("person")
    public Person person() {
        System.out.println("给容器中添加Person...");
        return new Person("张三", 11);
    }


/**
     * @Conditional 按照一定的条件进行判断,满足条件给容器中注册bean
     *
     * 如果是windows系统,给容器中注册Bill
     * 如果是linux系统,给容器中注册Gates
     *
     */

    @Conditional({WindowsConditon.class})
    @Bean("Bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional({LinuxConditon.class})
    @Bean("Linux")
    public Person person02() {
        return new Person("Linux", 50);
    }

public class LinuxConditon implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("linux")) {
            return true;
        }
        return false;
    }
}

public class WindowsConditon implements Condition {

    /**
     * ConditionContext 判断条件能使用的上下文环境
     * AnnotatedTypeMetadata 注释信息
     * @param context
     * @param metadata
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 1.能获取到ioc使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 2.类加载器
        ClassLoader classLoader = context.getClassLoader();
        // 3.环境信息
        Environment environment = context.getEnvironment();
        // 4.bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        return false;
    }
}

3.@Import 快速给容器导入一个组件

       1)@Import(要导入到容器中的组件),容器会自动注册该组件,id默认是全类名

       2)ImportSelector 返回需要导入的组件的全类名数组

       3)ImportBeanDefinitonRegistrar 手动注册bean到容器中

@Configuration
@Import({Color.class,Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {}

/**
 *自定义逻辑需要导入的组件
 *
 */
public class MyImportSelector implements ImportSelector {

    /**
     * AnnotationMetadata 当前标注@Import注解的类的所有注释信息
     *
     * @param importingClassMetadata
     * @return 返回值就是导入到容器中的组件的全类名
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.dingaimin.bean.Blue", "com.dingaimin.bean.Yellow"};
    }
}


public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     * AnnotationMetadata 当前类的注释信息
     * BeanDefinitionRegistry BeanDefinition注册类
     *      把所有需要添加到容器中的Bean 调用BeanDefinitionRegistry.registerBeanDefiniton手动注册
     *
     * @param importingClassMetadata  当前类的注解信息
     * @param registry  BeanDefinition注册类
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean definition = registry.containsBeanDefinition("com.dingaimin.bean.Red");
        boolean definition2 = registry.containsBeanDefinition("com.dingaimin.bean.Blue");
        if (definition && definition2) {
            // 指定Bean定义信息 Bean的类型,Bean...
            RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
            // 注册一个Bean,指定bean名
            registry.registerBeanDefinition("rainBow", beanDefinition);
        }
    }
}

4.使用spring提供的工厂bean(FactoryBean)

      1) 默认获取到的是工厂bean 调用 getObject创建的对象

      2)要想获取工厂bean本身,需要在id前面加个前缀标识符 &

/**
 * Spring定义的FactoryBean
 *
 */
public class ColorFactoryBean implements FactoryBean<Color> {

    /**
     * 返回一个Color对象,将对象添加到容器中
     *
     * @return
     * @throws Exception
     */
    @Override
    public Color getObject() throws Exception {
        System.out.println("ColorFactoryBean ... getObject...");
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    /**
     * 是单例?
     * true 单例,在容器中存储一个
     * false 多实例,每次获取都会创建一个bean
     *
     * @return
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

public class IOCTest {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);

    @Test
    public void testImport() {
        printBeans(context);

        // 工厂Bean获取的是调用getObject创建的对象
        Object bean = context.getBean("colorFactoryBean");
        Object bean2 = context.getBean("colorFactoryBean");
        System.out.println("bean的类型:" + bean.getClass());
        System.out.println(bean == bean2);

        Object bean3 = context.getBean("&colorFactoryBean");
        System.out.println(bean3.getClass());
    }
}

输出结果:

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
mainConfig2
com.dingaimin.bean.Color
com.dingaimin.bean.Red
com.dingaimin.bean.Blue
com.dingaimin.bean.Yellow
person
Bill
colorFactoryBean
rainBow
ColorFactoryBean ... getObject...
ColorFactoryBean ... getObject...
bean的类型:class com.dingaimin.bean.Color
false
class com.dingaimin.bean.ColorFactoryBean

小结:


     给容器注册组件:
     1.包扫描+组件标注注解(@Controller/@Service/@Repository/@Component) --局限于自己写的类
     2.@Bean 导入第三方包里的组件
     3.@Import 快速给容器中导入一个组件
          1) @Import(要导入到容器中的组件),容器中会自动注册这个组件,id默认是全类名
          2)ImportSelector:返回需要导入的组件的全类名数组
          3) ImportBeanDefinitionRegistrar  手动注册Bean到容器中
     4.使用Spring提供的 FactoryBean (工厂Bean)
          1) 默认获取到的是工厂Bean调用getObject创建的对象
          2)要获取工厂bean本身,需要在id前面加个前缀标识 &

猜你喜欢

转载自blog.csdn.net/dam454450872/article/details/82897172
今日推荐