概述

给容器中注册组件一共有 4 种方法


  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前面加一个&
      &colorFactoryBean



一、@Configuration @Bean 给容器注册组件

传统的 XML 配置方式

在src 下定义类 Person
public class Person {

private String name;
private Integer age;

// 省略无参构造,有参构造,getter/setter,toString 方法
}
在 ​​resource/beans.xml​​ 里定义 bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="cn.duniqb.bean.Person">
<property name="age" value="18"/>
<property name="name" value="zs"/>
</bean>
</beans>
测试
public class MainTest {

public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
}
输出
Person{name='zs', age=18}

使用配置类

创建配置类

使用 @Bean 注解,可以显式地指定 id

/**
* 配置类等同于配置文件
* 标识这是一个配置类
*/
@Configuration
public class MainConfig {
/**
* 给容器注册一个 Bean
* @return 类型是返回值的类型,id 默认用方法名为 id
*/
@Bean("person")
public Person person01() {
return new Person("ls", 20);
}
}
测试
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
// 查看 bean 的id
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String s : namesForType) {
System.out.println(s);
}
}
}
输出
Person{name='ls', age=20}
person

二、组件扫描 @ComponentScan

以下会扫描出在 ​​cn.duniqb​​ 下的所有类

/**
* 配置类等同于配置文件
* 标识这是一个配置类
*/
@Configuration
@ComponentScan(value = "cn.duniqb")
public class MainConfig {

/**
* 给容器注册一个 Bean
*
* @return 类型是返回值的类型,id 默认用方法名为 id
*/
@Bean("person")
public Person person01() {
return new Person("ls", 20);
}
}
排除指定注解

指定扫描的时候按照什么规则排除那些组件,默认是空

Filter[] excludeFilters() default {};

以下会排除带有 @Controller 与 @Service 的组件

@Configuration
@ComponentScan(value = "cn.duniqb", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})
public class MainConfig {

/**
* 给容器注册一个 Bean
*
* @return 类型是返回值的类型,id 默认用方法名为 id
*/
@Bean("person")
public Person person01() {
return new Person("ls", 20);
}
}
包含指定注解
@Configuration
@ComponentScan(value = "cn.duniqb", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}, useDefaultFilters = false)
public class MainConfig {
/**
* 给容器注册一个 Bean
*
* @return 类型是返回值的类型,id 默认用方法名为 id
*/
@Bean("person")
public Person person01() {
return new Person("ls", 20);
}
}

三、@Scope 设置组件作用域

通过源码看出,Scope 有 4 个取值,分别是多实例,单实例,Web 环境下的单请求,Web 环境下的Session

单实例是默认值, ioc 容器会启动调用方法创建对象放到 ioc 容器中,以后每次获取都是从容器中拿取。

多实例时,每次获取时候才会调用方法创建对象。

/**
* Specifies the name of the scope to use for the annotated component/bean.
* <p>Defaults to an empty string ({@code ""}) which implies
* {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
* @since 4.2
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
* @see #value
*/
@AliasFor("value")
String scopeName() default "";
默认是是单实例的
@Configuration
public class MainConfig2 {
@Scope
@Bean("person")
public Person person() {
return new Person("zs", 25);
}
}
添加后是多实例
@Configuration
public class MainConfig2 {
@Scope("prototype")
@Bean("person")
public Person person() {
return new Person("zs", 25);
}
}

懒加载 @Lazy

单实例 bean,默认在容器启动时创建对象,懒加载是容器启动时不创建对象,在第一次获取时创建对象,并初始化,此时还是单实例。

@Configuration
public class MainConfig2 {
@Scope("prototype")
@Bean("person")
@Lazy
public Person person() {
return new Person("zs", 25);
}
}

四、按条件注册@Conditional

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

只有下面情况 true 时才会加载

public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

Environment environment = context.getEnvironment();

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

return false;
}
}

快速导入 @Import

在配置类上加注解即可实现注册

@Configuration
@Import(Color.class)
public class MainConfig2 {

}



没有修不好的电脑