Spring 之容器注册组件
概述
给容器中注册组件一共有 4 种方法
- 包扫描+组件标注注解
(@Controller
/@Service
/@Repository
/@Component
)[自己写的类] @Bean
[导入的第三方包里面的组件]@Import
[快速给容器中导入一个组件]@Import
(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名ImportSelector
:返回需要导入的组件的全类名数组;ImportBeanDefinitionRegistrar
:手动注册bean到容器中
- 使用
Spring
提供的FactoryBean
(工厂Bean);- 默认获取到的是工厂bean调用
getObject
创建的对象 - 要获取工厂Bean本身,我们需要给id前面加一个&
&colorFactoryBean
- 默认获取到的是工厂bean调用
一、@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 {
}
没有修不好的电脑