1. Spring - IOC - 注册组件

系列篇幅

前言

整理一下注册Bean的一些基础知识,本章重点

  • 组件的四种方式
  • 组件赋值的几种方式
  • 依赖注入

组件的四种方式

下面有详细写法,这里只是整理下方式,方便总结

方式相关注解用法
包扫描
组件标注方式
@Controller/@Service/@Repository/@Component自己写的类,如接口
@Bean@Bean导入第三方包里面的组件
@Import@Import快速给容器中导入一个组件
FactoryBean工厂Bean

容器中注册组件Id

注解组件Id例子
包扫描 + 组件标注方式首字母小写类名BookController - bookController
@Bean 的方式方法名 or 注解修饰名方法person01 - person01
@Import 方式默认全类名com.example.bean.Blue
FactoryBean首字母小写类名BookController - bookController

引入依赖

lombok 推荐: [Lombok 的使用](…/…/Java/编程技巧/Lombok 的使用.md)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.12.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.10</version>
</dependency>

测试使用的Person

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
}

通过xml方式

定义bean 其他都是固定格式,你用idea 创建的时候会自动的,我就不补充了

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <bean id="person" class="org.example.demo.bean.Person" scope="singleton">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>

</beans>

使用

public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		Person bean = (Person) applicationContext.getBean("person");
		System.out.println(bean);
}

通过configure方式

@Configuration
public class MainConfig {
    @Bean
    public Person person() {
        return new Person("张三", 18);
    }
}
public static void main(String[] args) {
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    // 查找
		Person bean = applicationContext.getBean(Person.class);
		System.out.println(bean);
}

排除用法

@Configuration
@ComponentScan(basePackages = {"org.example"},excludeFilters = {
  //排除注解 @Controller
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
  //排除类 TestService.class
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {TestService.class}) })
public class MainConfig { }

Bean的Id

方式说明优先级
@Bean(“person02”)注解时命令
public Person person01()方法名
@Configuration
public class MainConfig {
    @Bean("person02")
    public Person person01() {
        return new Person("张三", 18);
    }
}

输出结果:Person02

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
  System.out.println(name);
}

@Import 方式

定义类

@Data
public class Color {
    private String color;
}

方式一:使用注解方式

@Configuration
@Import({Color.class})
public class MainConfig{}
AnnotationConfigApplicationContext 
  applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] names = applicationContext.getBeanDefinitionNames();
Stream.of(names).forEach(System.out::println);

输出

org.example.demo.bean.Color

方式二:使用ImportSelector接口

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

    /**
     * @param importingClassMetadata 当前标注@Import注解的类的所有注解信息
     * @return 要导入到容器中的组件全类名
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //方法不要返回null值
        return new String[]{"org.example.demo.bean.Color"};
    }

}
@Configuration
@Import({MyImportSelector.class})
public class MainConfig{}

方式三:通过 ImportBeanDefinitionRegistrar 接口,手动注册

@Configuration
@Import({Color.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig {}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * 把所有需要添加到容器中的bean;调用
     * BeanDefinitionRegistry.registerBeanDefinition手工注册进来
     * @param importingClassMetadata AnnotationMetadata:当前类的注解信息
     * @param registry BeanDefinitionRegistry:BeanDefinition注册类
     */
    @Override
    public void registerBeanDefinitions(
      AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean definition = registry.containsBeanDefinition("org.example.demo.bean.Color");
        if(definition){
            //指定Bean定义信息;(Bean的类型,Bean。。。)
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
            //注册一个Bean,指定bean名
            registry.registerBeanDefinition("blue", beanDefinition);
        }
    }

}

FactoryBean 接口方式

/**
 * 创建一个Spring定义的FactoryBean
 */
public class ColorFactoryBean implements FactoryBean<Color> {

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

    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }

    @Override
    public boolean isSingleton() {
        // 是否为单实例
        return false;
    }
}
@Configuration
public class MainConfig{
    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
}

使用

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] names = applicationContext.getBeanDefinitionNames();
Stream.of(names).forEach(System.out::println);
//工厂Bean获取的是调用getObject创建的对象
Object bean2 = applicationContext.getBean("colorFactoryBean");
Object bean3 = applicationContext.getBean("colorFactoryBean");
System.out.println("bean的类型:"+bean2.getClass());
System.out.println(bean2 == bean3);

Object bean4 = applicationContext.getBean("&colorFactoryBean");
System.out.println(bean4.getClass());

组件赋值

通过@Value +@PropertySource来给组件赋值

@Data
public class Person {
  //通过普通的方式
  @Value("小民")
  private String name;
  // spel方式来赋值
  @Value("#{18-3}")
  private Integer age;
  // 通过读取外部配置文件的值
  @Value("${person.clsName}") 
  private String clsName;
}

@Configuration
@PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置
public class MainConfig {
    @Bean
    public Person person() {
        return new Person();
    }
}
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页