Spring常用的三种注入方式+{集合注入(set注入一种)}

Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入,setter注入,基于注解的注入。

构造方法注入

先简单看一下测试项目的结构,用maven构建的,四个包:
entity:存储实体,里面只有一个User类
dao:数据访问,一个接口,两个实现类
service:服务层,一个接口,一个实现类,实现类依赖于IUserDao
test:测试包 

在spring的配置文件中注册UserService,将UserDaoJdbc通过constructor-arg标签注入到UserService的某个有参数的构造方法

如果只有一个有参数的构造方法并且参数类型与注入的bean的类型匹配,那就会注入到该构造方法中。

测试打印结果:jdbc-登录成功

注:模拟用户登录的loginUser方法其实只是打印了一条输出语句,jdbc实现的类输出的是:jdbc-登录成功,mybatis实现的类输出的是:mybatis-登录成功。

问题一:如果有多个有参数的构造方法并且每个构造方法的参数列表里面都有要注入的属性,那userDaoJdbc会注入到哪里呢?

问题二:如果只有一个构造方法,但是有两个参数,一个是待注入的参数,另一个是其他类型的参数,那么这次注入可以成功吗?

结果:会注入到只有一个参数的构造方法中,并且经过测试注入哪一个构造方法与构造方法的顺序无关

结果:失败了,即使在costract-arg标签里面通过name属性指定要注入的参数名userDao也会失败.

问题三:如果我们想向有多个参数的构造方法中注入值该在配置文件中怎么写呢?

参考写法:通过name属性指定要注入的值,与构造方法参数列表参数的顺序无关。

问题四:如果有多个构造方法,每个构造方法只有参数的顺序不同,那通过构造方法注入多个参数会注入到哪一个呢?

结果:哪个构造方法在前就注入哪一个,这种情况下就与构造方法顺序有关。

setter注入

配置文件如下:

注:上面这两种写法都可以,spring会将name值的每个单词首字母转换成大写,然后再在前面拼接上”set”构成一个方法名,然后去对应的类中查找该方法,通过反射调用,实现注入。

切记:name属性值与类中的成员变量名以及set方法的参数名都无关,只与对应的set方法名有关,下面的这种写法是可以运行成功的

还有一点需要注意:如果通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上,否则spring没有办法实例化对象,导致报错。

基于注解的注入

在介绍注解注入的方式前,先简单了解bean的一个属性autowire,autowire主要有三个属性值:constructor,byName,byType。

  • constructor:通过构造方法进行自动注入,spring会匹配与构造方法参数类型一致的bean进行注入,如果有一个多参数的构造方法,一个只有一个参数的构造方法,在容器中查找到多个匹配多参数构造方法的bean,那么spring会优先将bean注入到多参数的构造方法中。
     
  • byName:被注入bean的id名必须与set方法后半截匹配,并且id名称的第一个单词首字母必须小写,这一点与手动set注入有点不同。
     
  • byType:查找所有的set方法,将符合符合参数类型的bean注入。

下面进入正题:注解方式注册bean,注入依赖 

主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:

  1. @Component:可以用于注册所有bean
  2. @Repository:主要用于注册dao层的bean
  3. @Controller:主要用于注册控制层的bean
  4. @Service:主要用于注册服务层的bean

描述依赖关系主要有两种:

1、@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配

2、@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了

Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

集合注入:

java中的集合主要有:List,Set,Map,此外还有个Properties

新建一个web工程(我IDEMyEclipse6.5),新建两个包com.sw.action,com.sw.test
1. 在com.sw.action包中新建一个java文件:DI,内容如下:

[java] view plain copy
package com.sw.action;  
  
import java.util.List;  
import java.util.Map;  
import java.util.Properties;  
import java.util.Set;  
  
public class DI {  
  
 private Map map;  
  
 private Set Set;  
  
 private List list;  
  
 private Properties pro;  
  
 public Map getMap() {  
  return map;  
 }  
  
 public void setMap(Map map) {  
  this.map = map;  
 }  
  
 public Set getSet() {  
  return Set;  
 }  
  
 public void setSet(Set set) {  
  Set = set;  
 }  
  
 public List getList() {  
  return list;  
 }  
  
 public void setList(List list) {  
  this.list = list;  
 }  
  
 public Properties getPro() {  
  return pro;  
 }  
  
 public void setPro(Properties pro) {  
  this.pro = pro;  
 }  
}  

其实集合注入也属于set注入,因为这些属性都需要一个set方法才能注入成功,Spring框架运用大量的反射机制

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
 "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
 <bean id="di" class="com.sw.action.DI">
  <!-- List注入 -->
  <property name="list">
   <list>
    <value>list1</value>
    <value>list2</value>
    <value>list3</value>
   </list>
  </property>
  <!-- Set注入 -->
  <property name="set">
   <set>
    <value>set1</value>
    <value>set2</value>
    <value>set3</value>
   </set>
  </property>
  <!-- Map注入 -->
  <property name="map">
   <map>
    <entry key="1">
     <value>one</value>
    </entry>
    <entry key="2">
     <value>two</value>
    </entry>
    <entry key="3">
     <value>three</value>
    </entry>
   </map>
  </property>
  <!-- Properties注入 -->
  <property name="pro">
   <props>
    <prop key="1">one</prop>
    <prop key="2">two</prop>
    <prop key="3">three</prop>
   </props>
  </property>
 </bean>
</beans>

每一个集合类都有它固定的注入格式。每个property的name属性必须要跟DI类中申明的属性名要一致。

3. 在com.sw.test包中新建一个java文件:TestDI,内容如下:

package com.sw.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sw.action.DI;

public class TestDI {
 public static void main(String[] args) {
  ApplicationContext actx = new ClassPathXmlApplicationContext(
    "config-di.xml");
  DI di = (DI) actx.getBean("di");
  // 打印这些集合
  System.out.println(di.getList());
  System.out.println(di.getSet());
  System.out.println(di.getMap());
  System.out.println(di.getPro());
 }
}

运行该文件,结果如图所示,发现之前在xml文件里面设置的都打印出来了。
见1.jpg

猜你喜欢

转载自blog.csdn.net/jiangjunlanzhoulan/article/details/81259744