Spring学习

1 装配bean

1.1 自动装配

  • 具体步骤:
    1)普通的接口
    2)实现接口的类,使用@Component注解,告诉Spring需要为其创建bean(应该叫做创建组件类)
    3)开启组件扫描,为组件类创建bean
    4)通过@Autowried注解,自动注入到成员变量或方法参数中

示例代码:
接口1:

/**
 * 一个光盘接口
 */
public interface CompactDisc {
    void sing();//光盘的sing功能
}

接口1实现,使用@Component注解,表示组件类,会在spring 中创建bean

/**
 * CompactDisc实现类
 */
@Component
public class SgtPeppers implements CompactDisc {
    public void sing() {
        System.out.println("sgtPeppers的sing方法");
    }
}

接口2

/**
 * 一个光盘接口
 */
public interface CompactDisc {
    void sing();//光盘的sing功能
}

接口2实现

在构造器方法上使用了@Autowired标注,参数CompactDisc将由spring 中的bean来自动注入

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

    @Autowired
    public CDPlayer(CompactDisc compactDisc){
        this.compactDisc = compactDisc;
    }
    public void play() {
        System.out.println("播放器开始播放");
        compactDisc.sing();
    }
}

配置类

@Configuration 注解:表明该类为注解类

@ComponentScan注解:启动组件扫描功能,没有参数的@ComponentScan,默认扫描配置类同包下的组件

@Configuration
@ComponentScan
public class JavaConfig {

}

ok,以上几步,一个Spring的简单自动装配完成,如何测试?

CompactDiscTest为一个测试类

@RunWith(StringJunit4ClassRunner.class): 使用SpringJunit4ClassRunner.class,可以在测试开始的时候自动创建Spring的应用上下文

@ContextConfiguration: 表示加载配置,有几种加载的方式,这里,选用的是加载配置类。

@Autowired : 当变量上修饰了这个注解时,Spring会自动将创建号的bean赋值过去。

package com.spring.action;

import com.spring.action.autoconfig.CDPlayer;
import com.spring.action.autoconfig.CompactDisc;
import com.spring.action.autoconfig.JavaConfig;
import com.spring.action.autoconfig.MediaPlayer;
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;

//使用SpringJUnit4ClassRunner,可以在测试开始的时候自动创建Spring的应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//导入配置
@ContextConfiguration(classes = JavaConfig.class)
public class AutoconfigTest {
    @Autowired
    private CompactDisc compactDisc;

    @Autowired
    private MediaPlayer mediaPlayer;
    @Test
    public void play() {
        mediaPlayer.play();
    }
}

测试结果:可以看见,成功运行了sgtPeppers的实现方法

WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
播放器开始播放
sgtPeppers的sing方法

1.2 通过Java代码装配bean

  • 具体步骤:
    1)普通的接口
    2)实现接口的类,该类为需要装配到spring bean中
    3)配置类,由该类定义bean
    示例代码:
    接口1:(普通的接口)
package com.spring.action.javaconfig;

/**
 * 一个光盘接口
 */
public interface CompactDisc {
    void sing();//光盘的sing功能
}

接口1实现:(普通的类)

package com.spring.action.javaconfig;

/**
 * CompactDisc实现类
 */
public class SgtPeppers implements CompactDisc {
    public void sing() {
        System.out.println("sgtPeppers的sing方法");
    }
}

接口2:(普通的接口)

package com.spring.action.javaconfig;

/**
 * 媒体播放器
 */
public interface MediaPlayer {
    void play(); //一个播放方法
}
接口2实现:(在构造方法使用了@Autowired来自动注入CompactDisc参数)

package com.spring.action.javaconfig;

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

public class CDPlayer implements MediaPlayer {
    private CompactDisc compactDisc;

    @Autowired
    public CDPlayer(CompactDisc compactDisc){
        this.compactDisc = compactDisc;
    }
    public void play() {
        System.out.println("播放器开始播放");
        compactDisc.sing();
    }
}

配置类

@Configuration注解表明其为配置类

通过@Bean,将方法返回的实例作为Spring bean保存

在第二个方法中,@Bean 注解的方法会自动将bean注入到参数中。


package com.spring.action.javaconfig;

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

@Configuration
public class JavaConfig {
    //为sgtPeppers创建bean
    @Bean
    public CompactDisc compactDisc(){
        return new SgtPeppers();
    }
    //为DCPlayer创建bean
    @Bean
    public MediaPlayer mediaPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }
}

测试类:

package com.spring.action;

import com.spring.action.javaconfig.CompactDisc;
import com.spring.action.javaconfig.JavaConfig;
import com.spring.action.javaconfig.MediaPlayer;
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;

//使用SpringJUnit4ClassRunner,可以在测试开始的时候自动创建Spring的应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//导入配置
@ContextConfiguration(classes = JavaConfig.class)
public class JavaconfigTest {
    @Autowired
    private CompactDisc compactDisc;

    @Autowired
    private MediaPlayer mediaPlayer;
    @Test
    public void play() {
        mediaPlayer.play();
    }
}

测试结果

WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
播放器开始播放
sgtPeppers的sing方法

1.3 XML装配bean

  • 具体步骤:
    1)普通的接口
    2)实现接口的类,该类需要装配到spring bean中
    3)xml配置文件
    示例代码:
    接口1:

package com.spring.action.xmlconfig;

/**
 * 一个光盘接口
 */
public interface CompactDisc {
    void sing();//光盘的sing功能
}

接口1实现

package com.spring.action.xmlconfig;

/**
 * CompactDisc实现类
 */
public class SgtPeppers implements CompactDisc {
    public void sing() {
        System.out.println("sgtPeppers的sing方法");
    }
}

接口2

package com.spring.action.xmlconfig;

/**
 * 媒体播放器
 */
public interface MediaPlayer {
    void play(); //一个播放方法
}

接口2实现

package com.spring.action.xmlconfig;

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

public class CDPlayer implements MediaPlayer {
    private CompactDisc compactDisc;

    public CDPlayer(CompactDisc compactDisc){
        this.compactDisc = compactDisc;
    }
    public void play() {
        System.out.println("播放器开始播放");
        compactDisc.sing();
    }
}

XML配置文件

<constructor-arg>:借助构造器来注入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="sgtPeppers" class="com.spring.action.xmlconfig.SgtPeppers"/>

    <bean id="cdPlayer" class="com.spring.action.xmlconfig.CDPlayer">
        <constructor-arg name="compactDisc" ref="sgtPeppers"/>
    </bean>

</beans>

测试类

package com.spring.action;

import com.spring.action.xmlconfig.CompactDisc;
import com.spring.action.xmlconfig.MediaPlayer;
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;

//使用SpringJUnit4ClassRunner,可以在测试开始的时候自动创建Spring的应用上下文
@RunWith(SpringJUnit4ClassRunner.class)
//导入配置
@ContextConfiguration(locations = "classpath:site.xml")
public class XMLconfigTest {
    @Autowired
    private CompactDisc compactDisc;

    @Autowired
    private MediaPlayer mediaPlayer;
    @Test
    public void play() {
        mediaPlayer.play();
    }
}

运行结果

9月 11, 2018 5:15:28 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
信息: Refreshing [email protected]23b78d: startup date [Tue Sep 11 17:15:28 CST 2018]; root of context hierarchy
播放器开始播放
sgtPeppers的sing方法

1.4 bean的命名

1)没有明确命名bean的id,则id为类名首字母小写。如CDPlayer的bean id就是cDplayer
2)自定义ID

  • 方式一:
@Component("cDplayerName")
  • 方式二:
    @Name注解来自Java依赖注入规范(Java Dependency Injection),与@Component只有细微差别,大多数情况下可以互换【个人觉得知道就好,没必要用】
@Name("cDplayerName")

1.5 组件扫描包基础包设置

  • 方式一:类所在的包就是基础包
@ComponentScan
  • 方式二:指定基础包(String 形式)
@ComponentScan(“packageName”)
  • 方式三:指定基础包更清晰版(String形式)
@ComponentScan(basePackages = “packageName”)
  • 方式四:指定多个基础包(String 形式)
@ComponentScan(backPackages = {“packageName1”, ”packageName2”})
  • 方式五:通过类来设置类的所在的包为基础包
@ComponentScan(basePackageClasses={DemoClass.class, DemoClass2.class})

为什么要特地表明2、3、4是string 形式:因为String是类型不安全的(not type-safe),而5更加安全。5设置可以添加一个空标记接口,只用来设置基础包,这是有利于代码重构的

1.6 配置文件的加载

  • 方式一:自动加载当前类名+context.xml后缀的配置文件。如CDPlayerContext.xml
@ContextConfiguration
  • 方式二:加载配置类
@ContextConfiguration(classes = JavaConfig.class)
  • 方式三:加载多个配置类
@ContextConfiguration(classes = {JavaConfig.class, JavaConfig2.class})
  • 方式四:加载指定的xml文件
@ContextConfiguration(locations=”classpath:xxx.xml”)
  • 方式五:加载多个指定的xml文件
@ContextConfiguration(locations={“classpath:xxx.xml” , “classpath:xxx2.xml”})

注:用idea开发需要把xml文件放到resources中,idea不会读src下的静态资源文件~~~

1.7 利用构造器XML声明bean的各种方式

有<constructor-arg>标签就表示:它借助的是类的构造器。

  • 方式一:通过<constructor-arg>借助构造器注入初始化bean,name为参数名
 <bean id="cdPlayer" class="com.spring.action.xmlconfig.CDPlayer">
        <constructor-arg name="compactDisc" ref="sgtPeppers"/>
    </bean>
  • 方式二:通过c命名空间借助构造器注入初始化bean
 <bean id="cdPlayer" class="com.spring.action.xmlconfig.CDPlayer" c:compactDisc-ref="sgtPeppers"/>

Spring学习

  • 方式三:c命名空间索引写法
    0代表构造器的第一个参数,为什么要"_"呢,因为XML是不允许属性第一位是数字的
<bean id="cdPlayer" class="com.spring.action.xmlconfig.CDPlayer" c:_0-ref="sgtPeppers"/>

1.8 XML注入字面量(String、基本数据类型等)

  • 方式一:
 <bean id="cdPlayer" class="com.spring.action.xmlconfig2.CDPlayer">
        <constructor-arg name="compactDisc" ref="sgtPeppers"/>
        <constructor-arg name="name" value="字符串数据"/>
        <constructor-arg name="happy" value="String Data"/>
    </bean>
  • 方式二:C命名空间注册
    <bean id="cdPlayer" class="com.spring.action.xmlconfig2.CDPlayer"
          c:name="字符串数据"
          c:happy="String Data"
          c:compactDisc-ref="sgtPeppers">
    </bean>
  • 方式三:C命名空间索引
    <bean id="cdPlayer" class="com.spring.action.xmlconfig2.CDPlayer"
          c:_0="字符串数据"
          c:_1="String Data"
          c:_2-ref="sgtPeppers">
    </bean>
  • 方式四:装配集合

没有使用name,则按构造器参数顺序注入

<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="sgtPeppers" class="com.spring.action.xmlconfig3.SgtPeppers"/>

    <bean id="otherCDPlayer" class="com.spring.action.xmlconfig3.OtherCDPlay">
        <!--String title-->
        <constructor-arg value="title"/>
        <!--CompactDisc compactDisc;-->
        <constructor-arg ref="sgtPeppers"/>
        <!--List<String> stringList;-->
        <constructor-arg>
            <list>
                <value>a</value>
                <value>b</value>
                <value>c</value>
                <value>d</value>
            </list>
        </constructor-arg>
        <!--List<CompactDisc> compactDiscList;-->
        <constructor-arg>
            <list>
                <ref bean="sgtPeppers"/>
                <ref bean="sgtPeppers"/>
                <ref bean="sgtPeppers"/>
                <ref bean="sgtPeppers"/>
            </list>
        </constructor-arg>
        <!--Set<String> compactDiscs;-->
        <constructor-arg>
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
                <value>d</value>
            </set>
        </constructor-arg>
        <!--Set<CompactDisc> compactDiscSet;-->
        <constructor-arg>
            <set>
                <ref bean="sgtPeppers"/>
            </set>
        </constructor-arg>
    </bean>

</beans>

至此的注入,都是通过构造器进行注入。

1.9 属性注入

通过属性注入的CDPlayer类只能有一个无参构造器。需要提供属性的setter方法。name就是参数名

  • 方式一: 注入
    <bean id="cdPlayer" class="com.spring.action.xmlconfig4.CDPlayer">
        <property name="name" value="name"/>
        <property name="happy" value="happy"/>
        <property name="compactDisc" ref="sgtPeppers"/>
    </bean>
  • 方式二:p命名空间法注入
    <bean id="cdPlayer" class="com.spring.action.xmlconfig4.CDPlayer"
          p:name="name"
          p:happy="happy"
          p:compactDisc-ref="sgtPeppers"
    />

Spring学习

  • 方式三:属性注入集合
    <bean id="otherCDPlayer" class="com.spring.action.xmlconfig4.OtherCDPlay">
        <property name="title" value="title"/>
        <property name="compactDisc" ref="sgtPeppers"/>
        <property name="stringList">
            <list>
                <value>a</value>
                <value>b</value>
                <value>c</value>
                <value>d</value>
            </list>
        </property>
        <property name="compactDiscList" >
            <list>
                <ref bean="sgtPeppers"/>
                <ref bean="sgtPeppers"/>
                <ref bean="sgtPeppers"/>
                <ref bean="sgtPeppers"/>
            </list>
        </property>
        <property name="compactDiscs">
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
                <value>d</value>
            </set>
        </property>
        <property name="compactDiscSet">
            <set>
                <ref bean="sgtPeppers"/>
            </set>
        </property>
    </bean>
  • 方式四:utli空间装配集合
    p命名空间无法装配集合,只能装配值或者bean引用
    <util:list id="stringList">
        <value>a</value>
        <value>b</value>
        <value>c</value>
        <value>d</value>
    </util:list>

    <util:list id="compactDiscList">
        <ref bean="sgtPeppers"/>
        <ref bean="sgtPeppers"/>
        <ref bean="sgtPeppers"/>
        <ref bean="sgtPeppers"/>
    </util:list>

    <util:set id="compactDiscs">
        <value>a</value>
        <value>b</value>
        <value>c</value>
        <value>d</value>
    </util:set>

    <util:set id="compactDiscSet">
        <ref bean="sgtPeppers"/>
    </util:set>

    <bean id="otherCDPlayer" class="com.spring.action.xmlconfig4.OtherCDPlay"
          p:title="title"
          p:compactDisc-ref="sgtPeppers"
          p:stringList-ref="stringList"
          p:compactDiscList-ref="compactDiscList"
          p:compactDiscs-ref="compactDiscs"
          p:compactDiscSet-ref="compactDiscSet"
    />

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:property-path 引用一个bean的属性(或内嵌属性),并将其暴露为bean
util:set 创建一个java.util.Set类型的bean,其中包含值或引用

1.10 导入和混合配置

  • 方式一:avaConfig中导入其他的JavaConfig

示例代码:
CDConfig 中配置了一个CompactDisc bean

package com.spring.action.mixedconfig;

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

@Configuration
public class CDConfig {
    @Bean
    public CompactDisc compactDisc(){
        return new SgtPepper();
    }
}

CDPlayer通过@Import 注解,引入了CDConfig的配置,从而使用了CompactDisc bean

package com.spring.action.mixedconfig;

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

@Configuration
@Import(CDConfig.class)
public class CDPlayerConfig {
    @Bean
    public MediaPlayer mediaPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }
}

或者更好的办法,使用一个专门的上级配置类,来讲CDConfig和CDPlayerConfig组合在一起(CDPlayerConfig无需导入CDConfig,且两个配置类不用再使用@Configuration注解)

上级配置类,导入了两个class

package com.spring.action.mixedconfig;

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

@Configuration
@Import({CDConfig.class, CDPlayerConfig.class})
public class JavaConfig {
}

两个下级配置类,不需要@Configuration,也不需要@Improt

package com.spring.action.mixedconfig;

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

//@Configuration
public class CDConfig {
    @Bean
    public CompactDisc compactDisc(){
        return new SgtPepper();
    }
}
package com.spring.action.mixedconfig;

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

//@Configuration
//@Import(CDConfig.class)
public class CDPlayerConfig {
    @Bean
    public MediaPlayer mediaPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }
}
  • 方式二:JavaConfig中导入XML

示例代码:

JavaConfig:通过@ImportResource导入xml

package com.spring.action.mixedconfig;

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

//@Configuration
//@Import(CDConfig.class)
@ImportResource("classpath:cd-config.xml")
public class CDPlayerConfig {
    @Bean
    public MediaPlayer mediaPlayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }
}

cd-config.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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="sgtPepper" class="com.spring.action.mixedconfig.SgtPepper"/>
    <!--<bean id="cdPlayer" class="com.spring.action.mixedconfig.CDPlayer" c:_0-ref="sgtPepper"/>-->
</beans>
  • 方式三:在XML中引入JavaConfig
    CDConfig:同样的,不需要@Configuration
package com.spring.action.mixedconfig;

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

//@Configuration
public class CDConfig {
    @Bean("cdx")
    public CompactDisc compactDisc(){
        return new SgtPepper();
    }
}

XML: 通过标签引入,c:_o-ref=“cdx”,cdx对应的是CDCing的bean id

<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--<bean id="sgtPepper" class="com.spring.action.mixedconfig.SgtPepper"/>-->
    <bean class="com.spring.action.mixedconfig.CDConfig"/>
    <bean id="cdPlayer" class="com.spring.action.mixedconfig.CDPlayer" c:_0-ref="cdx"/>
</beans>
  • 方式四:在XML中导入XML
    使用<import>标签导入即可
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--<bean class="com.spring.action.mixedconfig.CDConfig"/>-->
    <!--<bean id="cdPlayer" class="com.spring.action.mixedconfig.CDPlayer" c:_0-ref="cdx"/>-->
    <import resource="cd-config.xml"/>
    <bean id="cdPlayer" class="com.spring.action.mixedconfig.CDPlayer" c:_0-ref="sgtPepper"/>
</beans>