zoukankan      html  css  js  c++  java
  • (四)依赖注入

    依赖注入(Dependency Injection,DI)。

    • 依赖 : 指Bean对象的创建依赖于Spring容器
    • 注入 : 指Bean对象中的属性 , 由容器来设置和装配

    注入的三种方式:

    构造器注入(有参无参)、setter注入、注解注入(自动装配)

    1、构造器注入

    默认情况下都是通过无参构造器注入,因为User类中存在隐式的无参构造方法,容器配置如下

        <bean id="user" class="com.alan.pojo.User">
            <property name="name" value="name from bean"/>
        </bean>

    而当User类中重载了有参构造方法时,则必须通过有参构造方法注入(同c命名空间注入) 。如下所示

    User类

    public class User{
        private String name;
        
        public User(String name){
            this.name = name;
        }
    }

    spring容器配置

    <!-- 第一种根据index参数下标设置 -->
    <bean id="user" class="com.alan.pojo.User">
        <!-- index指构造方法 , 下标从0开始 -->
        <constructor-arg index="0" value="alan"/>
    </bean>
    
    <!-- 第二种根据参数名字设置 -->
    <bean id="user" class="com.alan.pojo.User">
        <!-- name指参数名 -->
        <constructor-arg name="name" value="alan"/>
    </bean>
    
    <!-- 第三种根据参数类型设置 -->
    <bean id="user" class="com.alan.pojo.User">
        <constructor-arg type="java.lang.String" value="alan"/>
    </bean>

    引入p命名空间

    xmlns:p="http://www.springframework.org/schema/p"
    <!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
        <bean id="userp" class="com.alan.pojo.User" p:name="alan" p:age="18"/>


    2、setter注入*

    要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is 

    set示例:

    public class UserServiceImpl implements UserService {
        private UserDao userDao;
        // 利用set实现
        public void setUserDao(UserDao userDao) {
    
            this.userDao = userDao;
        }
    
        public void getUser() {
            userDao.getUser();
        }
    }

    新建student类,并生成相应set方法

        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;

    对于不同类型,在xml中的注入

    <bean id="addr" class="com.alan.pojo.Address">
        <property name="address" value="上海"/>
    </bean>
    
    <bean id="student" class="com.kuang.pojo.Student">
        <property name="name" value="小明"/>
        <property name="address" ref="addr"/><!-- bean注入-->
    
        <property name="books">
            <array>
                <value>西游记</value>
                <value>红楼梦</value>
                <value>水浒传</value>
            </array>
        </property>
    
        <property name="hobbys">
        <list>
            <value>听歌</value>
            <value>看电影</value>
            <value>爬山</value>
        </list>
        </property>
    
      <property name="card">
          <map>
              <entry key="中国邮政" value="456456456465456"/>
              <entry key="建设" value="1456682255511"/>
          </map>
      </property>
    
      <property name="games">
          <set>
              <value>LOL</value>
              <value>BOB</value>
              <value>COC</value>
          </set>
      </property>
    
      <property name="wife"><null/></property>
    
      <property name="info">
          <props>
              <prop key="学号">20190604</prop>
              <prop key="性别">男</prop>
              <prop key="姓名">小明</prop>
          </props>
      </property>
    
    </bean>

    3、自动装配、注解注入

    自动装配

    (1) 按名称的自动装配

    <bean id="user" class="com.alan.pojo.User" autowire="byName">
        <property name="name" value="alan"/>
    </bean>

    小结:

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

    1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
    2. 去spring容器中寻找是否有此字符串名称id的对象。
    3. 如果有,就取出注入;如果没有,就报空指针异常。

    (2)按类型的自动装配

    使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

    测试:

    将user的bean配置修改一下 : autowire="byType",并添加一个相同类型的bean

    <bean id="dog" class="com.alan.pojo.Dog"/>
    <bean id="cat" class="com.alan.pojo.Cat"/>
    <bean id="cat2" class="com.alan.pojo.Cat"/>
    
    <bean id="user" class="com.alan.pojo.User" autowire="byType">
        <property name="str" value="alan"/>
    </bean>

    此时报错:NoUniqueBeanDefinitionException

    删掉cat2,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。

    注解注入

    注解注入需要对容器进行一些配置

    引入相关约束文件头

    xmlns:context="http://www.springframework.org/schema/context"
    
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd

    开启注解支持

    <context:annotation-config/>

    @Autowired

    • @Autowired是按类型自动转配的,不支持id匹配。
    • 需要导入 spring-aop的包!

    将User类中的set方法去掉,使用@Autowired注解

    public class User {
        @Autowired
        private Cat cat;
        @Autowired
        private Dog dog;
        private String str;
    
        public Cat getCat() {
            return cat;
        }
        public Dog getDog() {
            return dog;
        }
        public String getStr() {
            return str;
        }
    }

    此时配置文件内容

    <context:annotation-config/>
    
    <bean id="dog" class="com.alan.pojo.Dog"/>
    <bean id="cat" class="com.alan.pojo.Cat"/>
    <bean id="user" class="com.alan.pojo.User"/>

    @Autowired(required=false) 说明:

    false,对象可以为null;true,对象必须存对象,不能为null。默认为true。

    @Qualifier

    • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
    • @Qualifier不能单独使用。

    配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!

    <bean id="dog1" class="com.alan.pojo.Dog"/>
    <bean id="dog2" class="com.alan.pojo.Dog"/>
    <bean id="cat1" class="com.alan.pojo.Cat"/>
    <bean id="cat2" class="com.alan.pojo.Cat"/>

    没有加Qualifier测试,直接报错,在属性上添加Qualifier注解

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

    @Resource

    • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
    • 其次再进行默认的byName方式进行装配;
    • 如果以上都不成功,则按byType的方式自动装配。
    • 都不成功,则报异常。

    实体类User

    public class User {
        //如果允许对象为null,设置required = false,默认为true
        @Resource(name = "cat2")
        private Cat cat;
        @Resource
        private Dog dog;
        private String str;
    }

    容器配置文件

    <bean id="dog" class="com.alan.pojo.Dog"/>
    <bean id="cat1" class="com.alan.pojo.Cat"/>
    <bean id="cat2" class="com.alan.pojo.Cat"/>
    <bean id="user" class="com.alan.pojo.User"/>

    测试成功

    删除cat2

    <bean id="dog" class="com.kuang.pojo.Dog"/>
    <bean id="cat1" class="com.kuang.pojo.Cat"/>

    User中不指定name

    @Resource
    private Cat cat;
    @Resource
    private Dog dog;

    测试成功

    结论:先进行byName查找,失败;再进行byType查找

    小结:

    @Autowired 根据类型自动装配,效果同byType,如果这些类的类型都相同,此时就需要使用@Qualifier明确指定使用哪个类,

    @Autowired和@Qualifier(value=“xx”)一起使用 则根据指定的名称自动装配,效果同byName

    @Resource,可以通过类型也可以通过名称自动装配,如果指定名称,则优先通过指定的名称装配,默认通过byName装配,再通过byType装配

  • 相关阅读:
    Packet for query is too large (1986748 > 1048576). You can change this value on the server by 异常
    解决springdatajpa插入大量数据速度慢的问题
    thymeleaf onclick方法向js方法传递参数
    git的使用(扫盲)
    【错误总结】Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
    SpringBoot集成Swagger(Swagger的使用),生成接口文档,方便前后端分离开发
    spring中后台接收参数总结
    PTA 03-树3 Tree Traversals Again (25分)
    PTA 03-树2 List Leaves (25分)
    PTA 03-树1 树的同构 (25分)
  • 原文地址:https://www.cnblogs.com/alanchenjh/p/12256230.html
Copyright © 2011-2022 走看看