Spring-依赖注入、注解自动装配

1、依赖注入

        1、构造器注入

        2、set方式注入

                依赖注入:

                                依赖:bean对象的创建依赖于容器

                                注入:bean对象中的所有属性,由容器来注入

         Address.java   

public class Address {
 
     private String address;
 
     public String getAddress() {
         return address;
    }
     public void setAddress(String address) {
         this.address = address;
    }
 }

       Student.java

package com.rk.pojo;

import java.util.*;


public class Student {

    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}

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

    <!--使用spring创建对象,在spring这些都称谓Bean-->
    <bean id="Address" class="com.rk.pojo.Address">
        <property name="addr" value="汉中市"></property>
    </bean>

    <bean id="Student" class="com.rk.pojo.Student">
        <!--第一种,普通值注入,value-->
        <property name="name" value="罗林"></property>

        <!--第二种,Bean注入,ref-->
        <property name="address" ref="Address"></property>


        <!--第三种,数组注入-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
            </array>
        </property>

        <!--第四种,集合注入-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>跑步</value>
                <value>看电影</value>
                <value>敲代码</value>
            </list>
        </property>


        <!--第五种,map注入-->
        <property name="card">
            <map>
                <entry key="班级" value="计19本一"></entry>
                <entry key="身份证号" value="1324618196161614"></entry>
            </map>
        </property>


        <!--第六种,set注入-->
        <property name="games">
            <set>
                <value>部落冲突</value>
                <value>穿越火线</value>
                <value>英雄联盟</value>
            </set>
        </property>


        <!--第七种,null注入-->
        <property name="wife">
            <null/>
        </property>
        <!--第八种,自定义类型注入-->
        <property name="info">
            <props>
                <prop key="username">root</prop>
                <prop key="password">luolin123</prop>
            </props>
        </property>
    </bean>
</beans>

3、扩展方式注入 

       1、 P命名空间注入 : 需要在头文件中加入约束文件

        导入约束 : xmlns:p="http://www.springframework.org/schema/p"

<!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
 <bean id="user" class="com.kuang.pojo.User" p:name="罗林" p:age="18"/>

        2、c 命名空间注入 : 需要在头文件中加入约束文件

        导入约束 : xmlns:c="http://www.springframework.org/schema/c

<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
 <bean id="user" class="com.kuang.pojo.User" c:name="罗林" c:age="18"/>

2、Bean的作用域

        在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象 .

Singleton(单利模式)

        当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">

Prototype(原型模式)

        当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将bean定义成prototype,可以这样配置:

 <bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>  
  或者
 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

Request

        当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>

自动装配说明:

  • 自动装配是使用spring满足bean依赖的一种方法

  • spring会在应用上下文中为某个bean寻找其依赖的bean。

Spring中bean有三种装配机制,分别是:

  1. 在xml中显式配置;

  2. 在java中显式配置;

  3. 隐式的bean发现机制和自动装配。

这里我们主要讲第三种:自动化的装配bean。

Spring的自动装配需要从两个角度来实现,或者说是两个操作:

  1. 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;

  2. 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;

组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。

1、autowire byName (按名称自动装配)

小结:

当一个bean节点带有 autowire byName的属性时。

        其他bean节点中的id名必须和该bean结点的set要设置的属性名一样,要小写

  1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。

  2. 去spring容器中寻找是否有此字符串名称id的对象。

  3. 如果有,就取出注入;如果没有,就报空指针异常。

2、autowire byType (按类型自动装配)

        使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。其他bean节点的id值可以随意设置,它会根据所需要的对象类型自动查找装配。

小结:

        byname的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法值一样

        bytype的时候,需要保持所有的bean的class唯一,并且这个bean需要和自动注入的属性值类型一致!

3、使用注解实现自动装配

1、在spring配置文件中引入context文件头

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:com/something/strategy.properties</value>
</property>
<property name="properties">
<value>custom.strategy.class=com.something.DefaultStrategy</value>
</property>
</bean>

<bean id="serviceStrategy" class="${custom.strategy.class}"/>

2、@Autowired

        在需要自动装配的属性或方法前加上注解

//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;

        Autowired是按byType 的方式装配的,所以被装配的bean结点的id值可以随意,如果有两个类型(全限定名称)一样的bean结点会报错,解决方案,配合@Qualifier使用  先根据byType查找,再根据byName查找

        @Qualifier

        @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配

        @Qualifier不能单独使用。

案例:

@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

2、@Resource

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;

  • 其次再进行默认的byName方式进行装配;

  • 如果以上都不成功,则按byType的方式自动装配。

  • 都不成功,则报异常。

    案例       

 @Resource(name="cart2")
    private Cat cat;
    @Resource
    private Dog dog;

   这里是给name属性赋值,@Qualifier是value属性

@Resource=@Autowired+ @Qualifier

小结

@Autowired与@Resource异同:

1、@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

2、@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用

3、@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

猜你喜欢

转载自blog.csdn.net/m0_46979453/article/details/120433330