Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系。因此可以说Spring容器对Bean的注册、管理可以说是它的核心内容,最重要的功能部分。
因此本文主要介绍:向Spring容器注册Bean的多种方式。
xml方式(老方式,现在使用得非常的少)
在resource类路径创建一个文件:beans.xml
<?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="com.sayabc.boot2demo1.bean.Person"> <property name="name" value="cuzz"></property> <property name="age" value="18"></property> </bean> </beans>
然后main函数采用ClassPathXmlApplicationContext来启动Spring容器容器:
public static void main(String[] args) { ApplicationContext applicationContext = createNewApplicationContext(); Person bean = applicationContext.getBean(Person.class); System.out.println(bean); //Person(name=fsx, age=18) } //创建、启动Spring容器 private static ApplicationContext createNewApplicationContext() { return new ClassPathXmlApplicationContext("classpath:beans.xml"); }
从这便可以看出,这个bean就直接放到Spring容器里面了。
@Configuration @Bean配置类的方式
创建一个配置类:
@Configuration //该注解就相当于一个xml配置文件 public class MainConfig { @Bean(value = "person") public Person person() { return new Person("fsx", 18); } }
这样我们使用AnnotationConfigApplicationContext来启动容器了:
//创建、启动Spring容器 private static ApplicationContext createNewApplicationContext() { return new AnnotationConfigApplicationContext(MainConfig.class); }
效果同上,同样能向容器中放置一个Bean。
@Bean若不指定value值,bean的id默认为方法名的名称。可以指定init-method,destroy-method方法。但是需要注意:单实例Bean容器是管理bean的init和destroy方法的,但是多实例bean容器只管帮你创建和init,之后Spring就不管了。
@Bean相关注解:@Scope、@Lazy等。
如果是单实例Bean,IOC容器启动时就立马创建Bean,以后获取都从容器里拿(当然你也可以加上@Lazy这个注解,让单实例Bean也懒加载)。如果是多实例Bean,Bean只有获取的时候,获取一次就创建一次。
使用@ComponentScan扫描注册组件
只要标注了注解就能扫描到,如:@Controller @Service @Repository @component
配置类中加上这个注解:
@Configuration //该注解就相当于一个xml配置文件 @ComponentScan("com.fsx") public class MainConfig { }
实体类上加上一个组件,让其能扫描到:
@Component public class Person { private String name; private Integer age; }
启动Spring容器输出可以看到:
//创建、启动Spring容器 private static ApplicationContext createNewApplicationContext() { return new AnnotationConfigApplicationContext(MainConfig.class); } 输出为: Person(name=null, age=null)
备注:这种扫描的方式,请保证一定要有空构造函数,否则报错的。
@ComponentScan有很多属性,可以实现更加精确的扫描。比如:basePackageClasses、includeFilters、excludeFilters、lazyInit、useDefaultFilters等。需要注意的是,要使includeFilters生效,需要useDefaultFilters=false才行,否则默认还是全扫。
FilterType枚举的过滤类型,可以实现注解、正则等的精确匹配。当然也能CUSTOM自己实现接口来过滤,功能不可谓不强大。
@Conditional按照条件向Spring中期中注册Bean
/* * @author Phillip Webb * @author Sam Brannen * @since 4.0 * @see Condition */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditional { /** * All {@link Condition}s that must {@linkplain Condition#matches match} * in order for the component to be registered. */ Class<? extends Condition>[] value(); }