spring 装配bean(二)


1. 创建应用对象之间协作关系的行为通常程序装配,这也是依赖注入的本质
2. spring装配bean的三种机制 , 通常显示的配置越少越好,当必须显示配置bean的时候,推荐使用比xml更加强大的javaConfig,只有当你想使用便利的xml命名空间的时候,才应该使用xml
①:通过xml中进行显示配置
②:在java中进行显示的配置
③:隐式的bean发现机制和自动装配
3. 自动化装配bean :spring从2个角度来实现自动化装配,组件扫描和自动装配组合在一起,能够将显示配置降到最低
①组件扫描(component scanning) spring会自动发现应用上下文中所创建的bean
②:自动装配(autowiring):spring会自动满足bean之间的依赖
③:创建可被发现的bean示例

--接口
package package2;
public interface CompactDis {
    void play();
}

--实现类
package package2;
import org.springframework.stereotype.Component;
//注明是组件类 告知spring要为这个类创建bean
//组件扫描默认是不启用的,所以需要显示配制一下spring,命令它去寻找带有@Component注解的类,并为其创建bean
@Component
public class Sgtprppers implements CompactDis{
    private String title="这是标题";
    private String artist="The Beatles";
    @Override
    public void play() {
        System.out.println(title+"==="+artist);
    }
}

--java版启动自动扫描
package package2;
import org.springframework.context.annotation.ComponentScan;
//@ComponentScan java配置启用组件扫描的方式
//如果没有其他配置的话,默认扫描的是与配置类相同的包及子包下带有@Component的注解类,自动为其创建bean
Configuration
@ComponentScan
public class CDPlayerConfig {
}

--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" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="package2"/>
</beans>

--test
//使用了springJunit4ClassRunner,测试开始的时候自动创建spring应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration 需要在哪加载配置java版本  @ContextConfiguration(classes=CDPlayerConfig.class)
//@ContextConfiguration("classpath:spring.xml")  xml版本
@ContextConfiguration(classes = CDPlayerConfig.class)
public class TestCd {

    @Autowired
    private CompactDis compactDis;

    @Test
    public void test() {
        Assert.notNull(compactDis);
    }
}

  1. 为组件扫面的bean命名,sping应用上下文中的所有的bean都会给一个id,当没有明确表明的时候,sping默认会把类名首字母小写当做id
//为bean命名
@Component("指定的名称")
@Named("指定的名称")//java依赖注入规范中所提供
  1. 设置组件扫面的基础包
@ComponentScan("需要扫描的包名")
//如果想要更加清晰的表明所设置的是基础包,可以通过basePackages属性进行配置,这里设置的基础包是String类型的,如果包名改变就会出现错误
@ComponentScan(basePackages="需要扫描的包名")
@ComponentScan(basePackages={"扫描包1","扫描包2"})

//可以通过设置包中所包含的类,这些类所所在的包将会作为组件扫描的基础包
@ComponentScan(basePackageClasses={配置类1.class,配置类2.class})

  • 通过为bean添加注解实现自动装配
package package2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer{
     private CompactDisc cd;

     //当Autowired注解添加到构造方法的时候,表明当Spring创建CDPlayer bean的时候 会通过这个构造器进行实例化
     // 并且会传入一个可设置给CompactDisc类型的bean
    //@Autowired 和Inject(来源Java依赖注入规范)效果类似
     @Autowired
    public CDPlayer(CompactDisc cd) {
        this.cd = cd;
    }

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

    //Autowired注解不进可以用在构造器上,还能用在属性的Setter方法上
    //不管是构造器、Setter方法 还是其它方法,Spring都会尝试满足方法参数上所声明的依赖
    //当只有一个bean匹配依赖需求的时候,这个bean会被装配起来,没有匹配的bean的时候会抛出异常,为了避免异常的出现,设置属性required=false
    //当required=false 的时候 spring会尝试自动装配,但是没有匹配的bean的话,spring会让这个bean处于未装配状态,如果存在多个将会抛出异常 表示没有明确指定用哪个bean装配
    @Autowired(required = false)
    public void setCd(CompactDisc cd) {
        this.cd = cd;
    }
}
  • 通过java代码装配bean
    ①:尽管在许多场景下都可以使用自动装配,但是有的时候需要明确配置,例如 将第三方组件装配到应用中,这时候是没有办法使用自动装配的.显示的声明bean的时候有2中方式 java代码和xml
    ②带有@bean注解的方法可以采用任何必要的java功能来产生bean实例,构造器和set方法只是@Bean的2个简单样例
    //@Bean会告诉spring这个方法返回一个对象,该对象要注册为spring应用上下文中的bean
    @Bean
    public CompactDis sgtPeppers(){
        return  new sgtPeppers();
    }

    //默认情况下 bean的id与带有@Bean注解的方法名是 一样的 可以通过name进行重新命名
    @Bean(name="ss")
    public CompactDis sgtPeppers(){
        return  new sgtPeppers();
    }

    //这个方法并没有使用默认的构造器创建实例,而是调用了需要传入对象来构造实例
    //bean默认是单例的
    //这种是通过方法调用
    @Bean
    public CDPlayer cdPlayer(){
        return new CDPlayer(sgtPeppers())
    }

    //当做参数调用
    @Bean
    public CDPlayer cdPlayer(CompactDis compactDis){
        return new CDPlayer(compactDis)
    }
  • 通过xml装配bean
      <!-- bean标签类似于JavaConfig中@Bean注解 class是全限定的类名 -->
    <bean id="sgtprppers" class="package2.Sgtprppers"/>

    <!--当没有指定id的时候 这个bean将会根据全限定名来进行命名"package2.Sgtprppers#1 有2个就是 package2.Sgtprppers#2
        在基于JavaConfig的配置中我们需要直接负责创建bean的实例,在xml中默认调用构造器创建不用人为干预
     -->
    <bean  class="package2.Sgtprppers"/>

    <!--当spring遇到这个bean元素的时候,她会创建一个CDPlayer实例
     <constructor-arg ref="compactDis"/> 元素会告知spring将要一个id为compactDis的bean引用传递到CDPlayer构造器中
     作为替代方案可以使用spring的C-命名空间 必须引入标题头  xmlns:c="http://www.springframework.org/schema/c"
    -->
    <bean id ="cdPlayer" class="package2.CDPlayer">
        <constructor-arg ref="compactDis"/>
    </bean>

    <!--使用c-命名空间和声明构造参数
        属性名 c:开头 也就是命名空间的前缀 接下来就是要装配的构造器参数名 然后-ref  最后引用的bean id 
    -->
    <bean id ="cd" class="package2.CDPlayer" c:cd-ref="compactDis"/>

    <!--优化版
        将参数吗替换成参数的索引,防止改参数名报错 因为xml中不允许数字作为属性的第一个字符,因为必须添加下划线作为前缀
        当只有一个参数的时候可以 直接写c:_-ref
    -->
    <bean id ="cd2" class="package2.CDPlayer" c:_0-ref="compactDis"/>
  • 将字面量注入到构造器中
    private String title;
    private List<String> tracks;

<!--
   因为是构造参数必须要声明它  可以传null 当调用方法的时候就会出现空指针异常
   -->
    <bean id="balkDiscList" class="package2.BalkDiscList">
        <constructor-arg value="xxx"/>
        <constructor-arg><null/></constructor-arg>
    </bean>

    <!--给List赋值  预制类似我们也可以使用<ref>元素替代<value>,实现bean引用列表的装配
        <list>
            <red bean="xxx1"/>
            <red bean="xxx2"/>
        <list>
       set与list赋值区别不大 但是set会忽略重复的值,存放顺序不能保证
    -->
    <bean id="balkDiscList1" class="package2.BalkDiscList">
        <constructor-arg value="xxx"/>
        <constructor-arg>
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </constructor-arg>
  • 设置属性
public class CDPlayer {
    //
    private CompactDis compactDis;
    @Autowired
    public void setCompactDis(CompactDis compactDis) {
        this.compactDis = compactDis;
    }

    public void play(){
        compactDis.play();
    }
}

 <!--在创建bean的时候不会报错 但是调用方法的时候会报空指针异常 因为没有注入调用的那个属性-->
    <bean id="cdPlayer" class="package2.CDPlayer"/>

    <!--property元素为属性的set方法提供与constructor-arg 元素相同的功能
        此处可以使用p标签 引入头 xmlns:p="http://www.springframework.org/schema/p"
        p标签与c标签类似
    -->
    <bean id="cdPlayer2" class="package2.CDPlayer">
        <property name="compactDis" ref="compactDis"></property>
    </bean>

    <!--
    p标签使用规则
    p:compactDis(属性名)-ref(注入bean引用)="所注入bean的id"
    -->
    <bean id="cdPlayer2" class="package2.CDPlayer" p:compactDis-ref="compactDis"></bean>
  • 设置属性的字面量
public class BalkDiscList {
    private String title;
    private List<String> tracks;

    public void setTitle(String title) {
        this.title = title;
    }

    public void setTracks(List<String> tracks) {
        this.tracks = tracks;
    }


}

<!-- p标签与c标签一样  没有ref的是给字面量赋值
    我们不能使用p:标签来装配集合 但是我们可以使用 spring util-命名空间来简化
    引入标签头        xmlns:util="http://www.springframework.org/schema/util"
    -->
    <bean id="really" class="package2.BalkDiscList">
        <property name="title" value="xxx"/>
        <property name="tracks">
            <list>
                <value>1</value>
                <value>2</value>
            </list>
        </property>
    </bean>


    <!--使用util标签-->
    <util:list id="trackList">
        <value>1</value>
        <value>2</value>
    </util:list>
    <bean id="really" class="package2.BalkDiscList" p:title="xxx" p:tracks="trackList"/>
  • spring util-命名空间中的元素
<util:constant> 引入某个类型的public static域,并将器暴露为bean
<util:list> 创建一个java.util.List类型的bean,其中包含值和引用
<util:map>  创建一个java.util.Map类型的bean,其中包含值和引用
<util:properties>  创建一个java.util.properties类型的bean
<util:properties-path> 引用一个bean的属性(或内嵌属性),并将其暴露为bean
<util:set> 创建一个java.util.Set类型的bean,其中包含值和引用
  • 导入和混合配置
    在spring应用中,尽管可能会同时使用自动化和显示配置,即便你更喜欢通过javaConfig实现显示配置,但是有的时候XML确是最佳的方案
    关于混合配置,第一件事需要了解就是自动装配时,它并不在意要装配的bean来自哪里
@Configuration
public class CDConfig {
    @Bean
    public CompactDis compactDis() {
        return new SgtPeppers();
    }
}

//compactDis()方法已经移除,我们需要将两个类组合到一起
//一种是使用@Import注解导入 CDConfig
//或者采用一种更高级的方法 去创建一个更高级别的配置 同时引入这两个配置类@Import({CDConfig.class,CDPlayerConfig.class})
@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig {

    @Bean
    public CDPlayer cdPlayer(CompactDis compactDis){
        return new CDPlayer(compactDis);
    }

}
//当一个类配置在xml中 一个是通过javaConfig配置的时候 可以类中使用注解@ImportResource("classpath:xml文件名")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值