Spring配置

作者: 小杨小杨神采飞杨 | 来源:发表于2020-04-19 17:23 被阅读0次

别名

<!--为已关联的bean取别名,之前的名字不会被覆盖,等于多了一个名字-->
<alias name="test" alias="mytest"/>

Bean的配置

<!--
id : bean的唯一标识符
class : bean对象对应的全限定名,包名+类名
name : 别名,且比alias更高级,可以取多个,分隔符多种多样
-->
<bean id="test" class="testClass" name="t1,t2 t3;t4">
</bean>

import

一般用于团队开发,将不同成员负责的不同配置导入到同一个配置中,之后使用这个配置便可以使用所有导入的配置

多个配置以及总配置
导入
之后使用applicationContext即可使用beans、beans2、beans3所配置的bean
注意:若内部配置的bean名称相同且内容相同,spring会自动覆盖成一个

复杂注入实验环境搭建

1、创建复杂实体类

public class student {
    //普通值
    private String isStr;
    //类参数
    private address isAddr;
    //数组
    private String[] isStrs;
    //list集合
    private List<String> isList;
    //map集合
    private Map<String,String> isMap;
    //set集合
    private Set<String> isSet;
    //properties配置文件
    private Properties isProperties;
    //null空指针
    private String isNull;

    @Override
    public String toString() {
        return  "isStr='" + isStr + '\'' +
                "\nisAddr=" + isAddr.getCity() +
                "\nisStrs=" + Arrays.toString(isStrs) +
                "\nisList=" + isList +
                "\nisMap=" + isMap +
                "\nisSet=" + isSet +
                "\nisProperties=" + isProperties +
                "\nisNull='" + isNull + '\'';
    }

    public String getIsStr() {
        return isStr;
    }

    public void setIsStr(String isStr) {
        this.isStr = isStr;
    }

    public address getIsAddr() {
        return isAddr;
    }

    public void setIsAddr(address isAddr) {
        this.isAddr = isAddr;
    }

    public String[] getIsStrs() {
        return isStrs;
    }

    public void setIsStrs(String[] isStrs) {
        this.isStrs = isStrs;
    }

    public List<String> getIsList() {
        return isList;
    }

    public void setIsList(List<String> isList) {
        this.isList = isList;
    }

    public Map<String, String> getIsMap() {
        return isMap;
    }

    public void setIsMap(Map<String, String> isMap) {
        this.isMap = isMap;
    }

    public Set<String> getIsSet() {
        return isSet;
    }

    public void setIsSet(Set<String> isSet) {
        this.isSet = isSet;
    }

    public Properties getIsProperties() {
        return isProperties;
    }

    public void setIsProperties(Properties isProperties) {
        this.isProperties = isProperties;
    }

    public String getIsNull() {
        return isNull;
    }

    public void setIsNull(String isNull) {
        this.isNull = isNull;
    }
}

2、创建配置文件

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">



</beans>

依赖注入

1、构造器注入
参考spring入门(https://www.jianshu.com/p/133db8383263)的构造器注入
2、set注入(重点)

  • 依赖注入
    • 依赖:bean对象的创建依赖容器
    • 注入: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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--创建bean-->
    <bean id="addr" class="address">
        <property name="city" value="杭州"/>
    </bean>

    <!--创建bean-->
    <bean id="stu" class="student">
        <!--注入普通值-->
        <property name="isStr" value="杨子贤"/>

        <!--注入bean-->
        <property name="isAddr" ref="addr"/>

        <!--注入数组-->
        <property name="isStrs">
            <array>
                <value>《红楼梦》</value>
                <value>《西游记》</value>
                <value>《三国演义》</value>
                <value>《水浒传》</value>
            </array>
        </property>

        <!--注入list集合-->
        <property name="isList">
            <list>
                <value>1111</value>
                <value>2222</value>
                <value>3333</value>
            </list>
        </property>

        <!--注入map集合-->
        <property name="isMap">
            <map>
                <entry key="key1" value="value1"/>
                <entry key="key2" value="value2"/>
                <entry key="key3" value="value3"/>
            </map>
        </property>

        <!--注入set集合-->
        <property name="isSet">
            <set>
                <value>4444</value>
                <value>5555</value>
                <value>6666</value>
            </set>
        </property>

        <!--注入properties配置文件-->
        <property name="isProperties">
            <props>
                <prop key="driver">cn.jdbc.cj.xxx</prop>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>

        <!--注入null空指针-->
        <!--设置空字符串-->
        <!--<property name="isNull" value=""/>-->
        <!--设置null值-->
        <property name="isNull">
            <null/>
        </property>
    </bean>

</beans>
运行结果
补充:
1、如上导入list、map等复杂数据时,每次都手动是很麻烦的,尤其是有很多重复集合的时候,此时可以使用util来简化,导入util命名空间
导入命名空间
        <util:list id="list"> <!--等于为list创建了一个bean,使用容器对象get也可以获取-->
                    <value>1111</value>
                    <value>2222</value>
                    <value>3333</value>
        </util:list>
<!--注入list集合-->
        <property name="isList" ref="list"> <!--此时使用ref引入即可-->
<!--            <list>-->
<!--                <value>1111</value>-->
<!--                <value>2222</value>-->
<!--                <value>3333</value>-->
<!--            </list>-->
        </property>

2、可以使用级联赋值的方式,直接修改已经引入的对象属性的属性,注意:一修改,引用的对象本身的该属性也会被修改


级联属性赋值

3、可以使用parent指定继承已注册的同类型的bean信息,此时再对属性进行赋值,会覆盖父类信息


继承
4、使用abstract将一个已注册的bean设为抽象bean,使得该bean只能被继承,无法被调用
抽象

若调用被abstract修饰的bean会报错


报错

5、使用depends-on可以决定bean创建的顺序,了解即可
6、使用工厂模式创建bean

  • 静态工厂:直接使用工厂.工厂方法()创建
public class staticFactory {
    public static airPlane getAirPlane(String id) {
        System.out.println("静态工厂正在制造飞机.....");
        airPlane air = new airPlane();
        air.setName("兴邦航空");
        air.setId(id);
        air.setCaptionName("张机长");
        air.setEditName("李维修长");
        return air;
    }
}
  • 动态工厂:需要先实例化工厂本身
public class dynamicFactory {
    public airPlane getAirPlane(String id) {
        System.out.println("动态工厂正在制造飞机.....");
        airPlane air = new airPlane();
        air.setName("兴邦航空");
        air.setId(id);
        air.setCaptionName("张机长");
        air.setEditName("李维修长");
        return air;
    }
}
  • Factorybean实现类:spring本身的factory接口
import org.springframework.beans.factory.FactoryBean;
import pojo.airPlane;

public class myFactoryBean implements FactoryBean<airPlane> {

    public airPlane getObject() throws Exception { //获取对象的方法
        System.out.println("Spring工厂正在制造飞机.....");
        airPlane air = new airPlane();
        air.setName("兴邦航空");
        air.setId("1003");
        air.setCaptionName("张机长");
        air.setEditName("李维修长");
        return air;
    }

    public Class<?> getObjectType() { //获取对象的类型
        return airPlane.class;
    }

    public boolean isSingleton() { //获取对象的方式是否为单例,false表示为单例,true表示不为单例
        return false;
    }
}

使用工厂创建bean:
1、静态
无需实例化工厂本身,调用方法创建对象


调用静态工厂的方法实例化对象
测试结果

可见调用工厂创建对应实体类成功
2、动态


实例工厂
测试结果
3、Factorybean实现类,这样方式的好处是,天生的有懒加载的效果,只在调用时才会实例化对象,且有更高级的功能
Factorybean实现类
测试结果
7、创建bean的生命周期方法

使用init-method指定初始化方法,使用destory-method指定销毁方法
8、使用spring管理数据库连接池,可见,spring默认的单例模式是非常适合web开发中使用的连接池的
首先导入依赖


导入依赖
在xml中注册连接池工厂bean静态工厂
注册bean
测试连接
测试结果

9、动态获取外部配置文件


导入命名空间 获取信息 测试成功

3、拓展方式注入

       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"

分别简化了set注入(p)和构造器注入(c)

<bean id="stu2" class="student"
          p:isStr="yzx_p"
          p:isAddr-ref="addr2"
          p:isStrs="1,2,3,4,5"
          p:isList="6,7,8,9,10"
          p:isSet="11,12,13,14,15">
        <!--注入普通值-->
        <!--注入bean-->
        <!--注入数组-->
        <!--注入list集合-->
        <!--注入map集合-->
        <!--注入set集合-->
        <!--注入properties配置文件-->
        <!--注入null空指针-->
        <!--设置空字符串-->
        <!--设置null值-->
    </bean>

<!--    <bean id="stu3" class="student"-->
<!--          c:isStr="yzx_c">-->
<!--    </bean>-->

bean的作用域

作用域

测试代码:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
student stu = context.getBean("stu", student.class);
student stu2 = context.getBean("stu", student.class);
System.out.println(stu == stu2);

singleton(spring默认机制):

<bean id="stu" class="student" scope="singleton">

运行结果:

结果
prototype:
<bean id="stu" class="student" scope="prototype">

运行结果:

结果
其余的只在web开发中使用,效果也与web中定义的一致

bean的自动装配

1、根据名称自动装配
缺点:名称不同则无法自动装配,多了之后容易乱

    <bean id="cat" class="Cat"/>
    <bean id="dog" class="Dog"/>

    <bean id="master" class="Master" autowire="byName">
        <property name="name" value="张三"/>
    </bean>

自动根据set方法后半段的名称将首字母小写后寻找同名bean,例如setDog,会自动寻找名为dog的bean进行装配

2、根据类型自动装配
缺点:类型不唯一时,无法自动装配,对用类型必须在bean中唯一

    <bean class="Cat"/>
    <bean class="Dog"/>

    <bean id="master" class="Master" autowire="byType">
        <property name="name" value="张三"/>
    </bean>

自动根据set方法需要的参数类型装配bean,无关名称,缺点是若有两个同类型set则无法自动装配,会报错,例如有两个dog类型的,则无法使用此方法自动装配
3、根据构造器自动装配


根据构造器匹配

4、自动装配集合


自动装配集合
测试结果

使用注解自动装配

开启注解自动装配
之后在实体类中指定属性或方法上使用@AutoWired注解即可,注意:只能对自定义类的属性使用,基本属性无效
属性上注解
方法上注解

装配规则:

  1. 首先根据类型(继承关系也算做同一类)去寻找已注册的bean,若找到一个同类型的bean,则自动注入,若一个都没找到,则抛出异常
  2. 若找到多个同类型的bean,则以变量名为id和找到的bean的id做匹配,若有id相同的则自动注入
  3. 若未找到匹配的id,会抛出异常,也可以使用@Qualifier来指定匹配的id名

使用@Qualifier("cat11")可以装配指定名称的bean,等于使用byname方式装配

Qualifier
若仍然找不到,则抛出异常,可见,使用@Autowired装配必须找到对应的bena,否则就会报错,此时,可以设置required属性,达到限制该属性是否可以为null的效果,false允许为null,true则不允许为null,同时使用@Nullable注解,也可以达到允许该属性为null的效果
required属性

使用非spring的注解@Resource也可以达到自动装配的效果


Resource

使用此注解,不指定name时,使用bytype,指定name时,使用byname,一个注解可达到两个注解的效果,且扩展性更强,因为这是J2EE定义的标准,但是因为抛开已经淘汰的EJB容器,只有spring一家容器框架,所以这个优点也不算优点了,了解即可

SpEL表达式

与EL表达式类似,但是spring的EL表达式更强大,可以调用静态方法和非静态方法


SPEL

泛型依赖注入

  1. 创建实体类


    目录结构
public abstract class basicDao<T> {
    public abstract void showInfo();
}

//bookDao和userDao分别使用注解注册,并集成basicDao

@Repository
public class userDao extends basicDao<user>{

    public void showInfo() {
        System.out.println("user.................");
    }
}

@Repository
public class bookDao extends basicDao<book>{

    public void showInfo() {
        System.out.println("book............");
    }
}
public class basicService<T> {

    @Autowired
    private basicDao<T> dao;

    public void showInfo() {
        dao.showInfo();
    }
}

//userService和bookSerive无任何实现,继承basicService即可

@Service
public class userService extends basicService<user>{

}

@Service
public class bookService extends basicService<book>{

}

此时basicService中自动注入的basicDao<T> dao无效,因为本身没有被注册到容器中,但是继承了他的两个子类,虽然无法调用basicDao<T> dao本身,但是可以获取showInfo方法,而他们也是有basicDao<T> dao这个属性的,只是不能使用而已,此时他们被注册了,则spring会自动注入已注册的userDao和bookDao的bean,而泛型被spring很只能的注入了

原理:
首先观察

观察
两个basicService的子类,在继承basicService时,都设置了各自的泛型为确定的一个对象,此时他们内部虽然没有东西,但是因为继承了basicService,所以他们其实是拥有了basicService的所有东西的,只是有些能用,有些不能用
拥有的东西
此时虽然basicService没有被注册到容器中,但是两个子类已经注册了,自动装配就会生效,而且会按照传入的泛型进行自动装配,即
自动装配
而userDao和bookDao继承了父类,也就有了父类的类型,他们已经注册到了容器中,所以自动装配时,会找到他们
有了父类的类型
刚好一一匹配,所以正常注入到了对应的属性中,由此可知:
注入一个类型的时候,他的泛型也是参考标准之一,使用父类的类型进行自动注入时,若父类有泛型,会使用带指定泛型的父类来进行自动注入

相关文章

  • Spring的java配置方式

    Spring的java配置方式 一、Spring的java配置方式 Java配置是Spring4.x推荐的配置方式...

  • SSM框架集成

    一、核心配置 配置spring-context.xml 配置spring-mvc.xml 配置web.xml 配置...

  • 第一章 Spring基础

    第一章 Spring基础 1.3 Spring 基础配置 1.3.2 Java配置 Java配置是Spring4....

  • Spring Mybatis初始化

    配置 欲在Spring中使用Mybatis,需要引入 在Spring配置文件中添加Spring配置 dataSou...

  • Spring学习笔记

    Spring基于XML方式的容器配置 Spring基于注解方式的容器配置 Spring基于Java方式的容器配置

  • 第1章: Spring 基础

    第1章:Spring 基础 spring 简史 xml配置spring1.x,主要配置各种Bean 注解配置spr...

  • Redis相关配置

    Spring XML配置 Spring application.properties 应用配置*maxActiv...

  • 6、Spring-XML配置

    一、概要 配置方式 Spring支持三种方式配置Bean,Spring1.0仅支持基于XML的配置,Spring2...

  • 2018-07-03(Spring配置文件浅析)

    Spring的配置文件就是Spring容器对bean进行设置,它是Spring的基础。 Spring的配置文件概述...

  • spring-jdbc

    spring-jdbc 导包:spring-tx spring-jdbc 一、xml配置方式 1、配置xml,...

网友评论

    本文标题:Spring配置

    本文链接:https://www.haomeiwen.com/subject/xfpybhtx.html