资讯专栏INFORMATION COLUMN

第二章 装配Bean

xcold / 1614人阅读

摘要:构造器自动装配方法自动装配其他方法自动装配不管是构造器,方法还是其他的方法,都会去尝试满足方法参数上所声明的依赖。所以上面的输出是构造器自动装配方法自动装配其他方法自动装配使用进行自动装配的时候,需要注意一下几点。

完整代码请见:https://github.com/codercuixi...
创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质。

2.1 Sprig配置的可选方案

在xml文件中显式配置(基本上公司中都不用了)
在Java中进行显式配置
隐式的bean发现机制和自动装配
建议:尽可能使用自动配置的机制,显式配置越少越好。
当你必须要显式配置bean的时候(比如源码不是由你来维护的,而你需要这些代码配置bean的时候),使用类型安全并且比xml更为强大的JavaConfig。
也就是自己写的尽量使用自动配置,他人的(第三方)使用JavaConfig

2.2 自动化配置Bean

主要通过两个角度来实现自动化配置
组件扫描(component scanning):Spring会自动发现应用上下文所创建的Bean
自动装配(autowiring):Spring会自动满足bean之间的依赖

2.2.1 创建可被发现的Bean

总共分为三步:
第一步,将要使用的Bean添加上@Component注解

package stereo_autoconfig.soundsystem;

import org.springframework.stereotype.Component;

/**
 * Create by cuixin on 2018/8/26
 **/
@Component
public class SgtPeppers implements CompactDisc {
    private String title = "Sgt.Peppers"s Lonely Hearts Club Band";
    private String artist = "The Beatles";
    @Override
    public void play() {
        System.out.println("Play "+title+" by "+ artist);
    }
}

第二步,通过@ComponentScan注解来扫描指定包及其子包中带有@Component注解的类

package stereo_autoconfig.soundsystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Create by cuixin on 2018/8/26
 * 通过@ComponentScan注解启动组件扫描,
 * 默认扫描所在包及其子包中带有@Component注解的类
 **/
@Configuration
@ComponentScan
public class CDPlayerConfig {
}

第三步,通过@ContextConfiguration配置上下文信息,也就是声明第二步中使用配置类

package stereo_autoconfig.soundsystem;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertNotNull;

/**
 * Create by cuixin on 2018/8/26
 **/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd);
    }

}
2.2.2 为组件扫描的bean命名

默认bean的id是将类名的第一个字母小写,比如上面的bean的ID就是sgtPeppers.
如果想要指定不同的ID,只需将值传给@Component注解。

@Component("lonelyHeartClub")
public class SgtPeppers implements CompactDisc {
    ...
}
2.2.3 设置组件扫描的基础包 方法一:基于String类型指定基础包.

Spring实战中说这种方式是类型不安全的,我使用IDEA重命名包时,只有在Refactor时选择Rename Package才会更改@ComponentScan中的String值,所以才说这是不安全的。
@ComponentScan默认的扫描的是所在包及其子包,如果你扫描其他包,或者想扫描多个包,应该怎么设置呢?指定不同的基础包

@Configuration //方式一,指定一个,通过设置value属性
@ComponentScan("stereo_autoconfig.soundsystem")
public class CDPlayerConfig {
}
@Configuration //方式二,指定一个,通过设置basePackages属性
@ComponentScan(basePackages = "stereo_autoconfig.soundsystem")
public class CDPlayerConfig {
}
@Configuration//方式三,指定多个,通过设置basePackages为数组
@ComponentScan(basePackages = {"stereo_autoconfig.soundsystem", "stereo_autoconfig.video"})
public class CDPlayerConfig {
}
方法二:基于包中所含的类或接口来指定基础包
@Configuration 
@ComponentScan(basePackageClasses = {CompactDisc.class, Video.class})
public class CDPlayerConfig {
}

当然为了重构时删除接口及相关类,你可以在包下面创建一个空标记接口(Marker Interface),专门用来指定基础包。

public Interface SoundSystemMarkerInface{
}
@Configuration 
@ComponentScan(basePackageClasses = {SoundSystemMarkerInface.class, Video.class})
public class CDPlayerConfig {
}
2.2.4 通过为bean添加注解实现自动装配

通过@ComponentScan,我们已经可以扫描得到Bean,但是如何装配这个Bean依赖的另一个bean呢?这就是自动装配解决的问题了。
简单来说,自动装配就是让Spring自动满足bean依赖的一种方法。

@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc cd;
    @Autowired
    public CDPlayer(CompactDisc cd){
        this.cd = cd;
        System.out.println("构造器 自动装配");
    }

    @Override
    public void play() {
        cd.play();
    }

    @Autowired
    public void setCompactDisc(CompactDisc cd){
        this.cd = cd;
        System.out.println("Setter方法 自动装配");
    }
    @Autowired(required = false)
    public void insertDisc(CompactDisc cd){
        this.cd = cd;
        System.out.println("其他方法 自动装配");
    }

}
package stereo_autoconfig.soundsystem;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertNotNull;

/**
 * Create by cuixin on 2018/8/26
 **/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
    @Autowired
    private CompactDisc cd;
    @Autowired
    private MediaPlayer player;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd);
    }

    @Test
    public void play(){
        player.play();
    }
}

不管是构造器,Setter方法还是其他的方法,Spring都会去尝试满足方法参数上所声明的依赖。上面依次会先执行构造器方法,
然后按照出现代码顺序执行其他自动注入方法。所以上面的输出是
构造器 自动装配
Setter方法 自动装配
其他方法 自动装配

使用@AutoWired进行自动装配的时候,需要注意一下几点。

第一点,假如有且只有一个bean匹配依赖需求的话,那么这个bean就会被装配进来。
第二点,如果没有匹配的bean,那么在应用上下文创建的时候spring会抛出一个异常。
为了避免异常的出现,可以将@AutoWired的required属性设置为false。但这可能导致这个bean处于未转配状态,使用的使用需要判断是否为空。
第三点,如果出现多个bean满足依赖关系的话,spring的@AutoWired自动装配也会抛出异常,因为他们不知道选哪一个

2.3 通过Java代码装配bean

当使用第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@ComponentScan和@AutoWired注解的,因此就不能使用自动化装配方案了。

JavaConfig比xml的优势:更为强大,类型安全,并且对重构友好。
尽管不是必须的,但通常会将JavaConfig放到多带带的包中,使他与其他的应用程序逻辑分离开来。
步骤:使用@Configuration创建配置类,并使用带有@Bean的方法声明bean,最后通过@ContextConfiguration来创建上下文

package stereo_javaconfig.soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Create by cuixin on 2018/8/26
 **/
@Configuration //创建配置类
public class CDPlayerConfig {
    @Bean //通过bean注解来声明简单的bean
    public CompactDisc compactDisc(){
        return new SgtPeppers();
    }
    @Bean(name = "cdPlayer") //bean id默认使用的方法名,使用方法参数实现注入,最优方法,可以将CompactDisc放在其他配置类中
    public CDPlayer cdPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }
//    @Bean(name = "cdPlayer2")
//    //bean id默认使用的方法名,引用创建bean的方法实现注入,spring会拦截所有compactDisc()调用,
//    // 确保按照规定(single,request,session)使用正确的bean,而不是简单地每次调用都生成一个
//    public CDPlayer cdPlayer2(){
//        return new CDPlayer(compactDisc());
//    }

}
package stereo_javaconfig.soundsystem;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import stereo_javaconfig.soundsystem.*;

import static org.junit.Assert.*;

/**
 * Create by cuixin on 2018/8/26
 **/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayeTest {
    @Autowired
    private MediaPlayer player;
    @Test
    public void player(){
        player.play();
    }
}
2.4 通过xml装配Bean(略)

只是维护早先代码的时候你才会用到这个。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76965.html

相关文章

  • Spring总结(一)

    摘要:如果这个类的方法有修饰,就成为第二种的装配方式代码生成要自动装配的类要保留默认构造函数,需要装配的属性使用来装配。显示装配分为两种,一种是代码装配,一种是装配。和相比,上面这种形式的中的是调用默认构造函数生成的。 Bean的自动装配 通过@ComponentScan扫描发现将要装配到ApplicationContext中的Bean。@ComponentScan中如果没有写包名,那么默...

    OpenDigg 评论0 收藏0
  • 慕课网_《Spring入门篇》学习总结

    摘要:入门篇学习总结时间年月日星期三说明本文部分内容均来自慕课网。主要的功能是日志记录,性能统计,安全控制,事务处理,异常处理等等。 《Spring入门篇》学习总结 时间:2017年1月18日星期三说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:https://github.com/zccodere/s...个人学习源码:https://git...

    Ververica 评论0 收藏0
  • Spring【依赖注入】就是这么简单

    摘要:前言在的第二篇中主要讲解了模块的使用容器创建对象的问题,模块主要是解决对象的创建和对象之间的依赖关系,因此本博文主要讲解如何使用容器来解决对象之间的依赖关系回顾以前对象依赖我们来看一下我们以前关于对象依赖,是怎么的历程直接对象在最开始,我们 前言 在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题,Spring Core模块主要是解决对象的创建和...

    Lyux 评论0 收藏0
  • 第三章 高级装配

    摘要:注解只可以装配只有一个实现类的例如下面的有三个实现类,自动装配时,就会不知道选哪一个,因而会报错误。使用表达式语言进行装配使用的来引用待补充实例调用方法和访问对象的属性对峙进行算数,关系和逻辑运算正则表达式匹配集合操作 完整代码请见:https://github.com/codercuixi... 第一部分 @Profile注解的使用 环境与profile 是否启用某个bean,常用于...

    only_do 评论0 收藏0
  • Spring详解3.Bean装配

    摘要:的依赖关系,根据依赖关系配置完成之间的装配。的行为信息,如生命周期范围及生命周期各过程的回调函数。使用该种装配模式时,优先匹配参数最多的构造函数。如果提供了默认的构造函数,则采用否则采用进行自动装配。 点击进入我的博客 1 Spring容器与Bean配置信息 Bean配置信息 Bean配置信息是Bean的元数据信息,它由一下4个方面组成: Bean的实现类 Bean的属性信息,如数...

    endiat 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<