spring中bean的装载

一:spring 对bean的装载方式

spring 对bean的装载方式存在三种:

  1. 在xml中进行显式配置;
  2. 在java中进行显式配置;
  3. 隐式的bean发现机制和自动装配;

二:自动化装配bean

spring 从两个角度来实现自动化装配:

组件扫描:spring会自动发现应用上下文中所创建的bean;
自动装配:spring自动满足bean之间的依赖;

1.创建可被发现的bean (@Component)
  首先我们需要确定需要创建的bean,这个bean并没有规定是一个什么样的类对象,只要我们需要将该类装配为一个bean,我们就可以在这个类上添加@Component这个注解,这个类可以是普通的Java类,也可以是一个接口的实现类,而这个注解的意思就是这个类会作为组件类,并告知spring要为这个类创建bean,因为这个注解的存在,使得spring会为我们把事情处理妥当。
  但是,组件扫描默认是不开启的,所以我们需要显式配置一下spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。
  以上方法是比较简单的创建bean的方式,我们也可以为组件扫描的bean命名,默认情况下,Spring应用上下文中所有的bean都会有一个默认id.这个id就是bean类的类名,只是类名的首字母变成了小写,我们也可以为这个bean设置不同的id,所要做的就是将期望的id作为值传递给@Component注解,比如我们想将这个bean标识为mydou,那么就需要将对应bean的类的@Component注解配置成:@Component(“mydou”)的方式。另外,还有一种为bean命令的方式,这种方式不使用@Component注解,而是使用java依赖注入规范中所提供的@Named注解来为bean设置id: @Named(“mydou”),Spring支持将 @Named作为@Component注解的替代方案,两者之间有细微差异,但在大多数场景下可以互换。
  
2. 启用组件扫描(@ComponentScan)
  我们需要显式的创建一个配置类,在这个配置类上使用@Configuration和@ComponentScan注解,该类上的注解定义了spring的装配规则,该类可以不显式地声明任何bean,只不过它使用了@ComponentScan注解,这个注解能够在spring中启用组件扫描,而@Configuration注解表明该类是一个配置类。
  如果没有其他配置,@ComponentScan注解默认会扫描该配置类所在包下的所有带有@Component注解的类,但如果我们想让其扫描其他包或者指定包下的带有@Component的注解的类时,我们就需要在@ComponentScan注解后添加basePakages属性,包名用双引号包裹,另外,backPakages字段也可以省略,直接写上包名就可以了。如果是多个基础包,用逗号隔开,同时用大括号包裹就可以了。如@ComponentScan(basePackages = {xxx, yyy})
  当然,除了设置基础包之外,也可以直接设置包中所包含的类或者接口。那么@ComponentScan注解后添加的是basePackageClasses属性,类的class文件不需要用引号,直接写就可以,如果有多个,逗号隔开,同时用大括号包裹,如@ComponentScan(basePackageClasses = {xxx.class,yyy.class})
  
3. 发现配置(@ContextConfiguration)
  通常,我们需要使用@RunWith(SpringRunner.class)注解来在启动项目的时候自动创建spring应用上下文,而注解@ContextConfiguration会告诉它需要在哪里加载配置(在上文2中提到的配置类中加载配置,如@ComponentScan(classes = xxConfig.class)),因为配置类中包含了@ComponentScan,因此最终的应用上下文中应该包含对应需要创建的bean。这样我们就可以使用@Autowired注解,让spring发现bean类,自动在spring上下文中将其创建为bean并将其注入到代码中了。
  在使用@Autowired注解时,当没有匹配的bean时,会抛出异常,如果不想让其抛出异常,需要设置该注解的required属性为false,但是设置为false需要谨慎,当设置为false时,spring会尝试执行自动装配,如果没有匹配的bean,那么spring会让这个bean处于未装配状态。如果有多个bean满足依赖关系的话,spring会抛出一个异常,表明没有明确指定要选择哪一个bean进行自动装配。
  除了@Autowired注解之外,@Inject注解在大多数场景下也可以和@Autowired注解互换,@Inject注解是Java依赖注入规范,而@Autowired注解是Spring特有的注解。

易错点:
1.一般如果bean未配置成功,会出现对应的@Autowired的bean对象为null,出现空指针异常,解决方案就是按上述方式装配bean就可以了。
2.一般依赖包导入未成功,会出现类似mocker布拉布拉之类的错误,解决方案,需要重新下载导入包(注意连网)

三:通过java代码装配bean

当我们需要将第三方库中的组件装配到自己的应用中的情况下,没有办法在其类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了,这种情况下就必须采用显式装配的方式。显式装配的方式有java和xml两种,但是java配置更加强大,类型安全并且对重构友好,一般会将javaConfig放到单独的包中,并且不应包含任何业务逻辑。
  此方式下,需要对要装配的bean在该配置文件中的方法中添加@Bean注解,在该注解上也可以添加name属性,为该方法重新命名,在此方式下,就不需要再在该配置类上添加@ComponentScan(basePackages = “com.mobisys.service.impl”)注解了,也不需要在要创建的bean类上添加@Component注解了,此方式相对于隐式的好处在于:当需要将第三方库中的组件装配到自己的应用的时候,隐式自动装配就无法做到,因为我们无法在第三方库中的组件,也就是要引用的bean类上为其添加@Component注解,只能采用显式方式来解决。

@Bean(name = "getPolyService")
public PolynomialService getPolyBean(){
   return new PolynomialServiceImpl();
}

四:其他问题

1. 使用xml文件进行bean装配的缺点
  当我们使用xml文件进行bean的装配的时候,会存在配置复杂的问题,并且我们手动配置bean的类型是字符串的形式设置在了class属性中,无法保证设置给class属性的值是真正的类,并且,spring的xml配置并不能从编译期的类型检查中受益,即使所引用的是实际的类型,如果重命名了类,也会装配失败。当我们使用xml文件进行bean的装配的时候,会存在配置复杂的问题,并且我们手动配置bean的类型是字符串的形式设置在了class属性中,无法保证设置给class属性的值是真正的类,并且,spring的xml配置并不能从编译期的类型检查中受益,即使所引用的是实际的类型,如果重命名了类,也会装配失败。
2. 多个Java的配置类文件组合问题
   当使用java代码来装配bean的方式中,当config文件所在类的bean方法过多时,我们可以将一部分拆开放入另一个配置文件中,但是我们如何将这已经拆开的多个配置文件中的多个类组合在一起?一种方法就是在拆出来的配置文件中的类上使用@Import注解来导入原来的配置类的class,如@Import(xxConfig.class)另一种方法就是不在已经拆出来的配置类上使用@Import注解,这几个拆出来的配置类都是平等的,就是使用原来的注解,以及在方法上使用@Bean注解,唯一要做的就是重新创建一个配置类,这个类用来将所有拆出来的配置类组合在一起,组合的方式就是在这个新的配置类上使用@Configuration和@Import({xxConfig.class, yyConfig.class}),并使用@ComponentScan注解来启用组件扫描
3. Java配置方式和xml文件配置方式组合问题
  当Java配置方式的配置类中,拆出来的bean需要用xml的方式来配置,那么如何将java配置的bean和xml方式配置的bean组合在一起,让spring同时加载它和其他基于Java的配置呢?解决方案就是使用@ImportResource注解,通过上一个问题,我们知道有一个全局配置类,它负责将所有配置bean的类组合起来,那么同样是这个配置类,我们假设xml配置的文件叫做zzConfig.xml,该文件位于根类路径下,那么可以修改那个全局的配置类,让它使用@ImportResource注解,如@ImportResource(“classpath:zzConfig.xml”),当然,也要使用@Import(xxConfig.class)来组合Java的配置类(@Configuration注解也不能少)。在全局的配置类上使用@ComponentScan注解来启用组件扫描

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值