3.Spring-依赖注入(DI)

本文最后更新于2022.06.08-12:35,某些文章具有时效性,若有错误或已失效,请在下方留言或联系涛哥

DI

IOC是一种思想 而依赖注入是 IOC的一种实现。

依赖注入的作用:在容器初始化对象时,把对象的属性进行赋值

依赖注入

1.设值注入

本质上是调用 类提供的属性的setter方法 进行属性赋值

<bean name="user" class="com.rimi.bean.User">
    <property name="username" value="admin"></property>
    <property name="password" value="123456"></property>
</bean>
  • name 代表 属性的名字(因为 spring容器会根据属性名去找对应的setter方法,所以 命名规范)
  • value 代表的属性的值

2.构造注入

本质上是调用 类的 有参的构造方法 进行属性的初始化

<bean name="user" class="com.rimi.bean.User">
    <constructor-arg name="username" value="admin"></constructor-arg>
    <constructor-arg name="password" value="123456"></constructor-arg>
    <constructor-arg name="userid" value="1"></constructor-arg>
</bean> 

使用构造注入时,bean中的 constructor-arg 的数目必须和 构造方法中 形参的数目一致

constructor-arg

  • name 代表的是形参的名字
  • value 形参的值
  • index 表示形参的编号
  • type 指定形参的类型。

使用方式:通常以设值注入为主,构造注入为辅。对于依赖关系不需要发生改变的注入,通常使用构造注入。

3.自动装配注入

本质上是调用 类的属性的 byType(类型模式),byName(名称模式)、constructor(构造函数模式),autodetect()进行属性的初始化

<bean name="user" autowire="byType"  class="com.rimi.bean.User">
    <property name="username" value="admin"></property>
</bean>
  • no: 不使用自动装配。Bean依赖必须通过ref元素定义。这是默认配置,在较大的部署环境中不鼓励改变这个配置,显式配置合作者能够得到更清晰的依赖关系。
  • byName: 根据setter方法名进行自动装配。Spring容器查找容器中全部Bean,找出其id与setter方法名去掉set前缀,并小写首字母后同名的Bean来完成注入。如果没有找到匹配的Bean实例,则Spring不会进行任何注入。
  • byType: 根据setter方法的形参类型来自动装配。Spring容器查找容器中的全部Bean,如果正好有一个Bean类型与setter方法的形参类型匹配,就自动注入这个Bean;如果找到多个这样的Bean,就抛出一个异常;如果没有找到这样的Bean,则什么都不会发生,setter方法不会被调用。
  • constructor: 与byType类似,区别是用于自动匹配构造器的参数。如果容器不能恰好找到一个与构造器参数类型匹配的Bean,则会抛出一个异常。
  • autodetect: Spring容器根据Bean内部结构,自行决定使用constructor或byType策略。如果找到一个默认的构造函数,那么就会应用byType策略。

4.注解注入

@Autowired

@Service
public class UserServiceImpl implements UserService{
    @AutoWired
    private UserDao userDao;
}
内部等同于
@Service
public class UserServiceImpl implements UserService{
    @AutoWired(required=true)
    private UserDao userDao;
}
同样也可以指定类型byNmae
@Service
public class UserServiceImpl implements UserService{
    @AutoWired(required=false)
    @Qualifier("userDao")
    private UserDao userDao;
}

@Resource

@Service
public class UserServiceImpl implements UserService{
    @Resource
    private UserDao userDao;
}
内部等同于
@Service
public class UserServiceImpl implements UserService{
    @Resource(name="userDao")
    private UserDao userDao;
}
同样也可以指定类型byType
@Service
public class UserServiceImpl implements UserService{
    @Resource(type=com.edu.dao.UserDao.class)
    private UserDao userDao;
}  
  • @Resource:用于依赖注入,注入的bean的名字 默认和对应的属性名一样即属性名为userDao @Resource(name="bean名字")来进行注入 使用@Resource进行注入,实现原理反射机制,所以即使属性没有set方法 或者构造方法,依然可以注入成功. 对于@Resource注解,如果没有指定注入的bean的名字,并且存在两个相同接口(类型)的bean,则会抛出异常。
  • @Autowired:用于依赖注入,默认以byType进行自动装配,当Spring容器中有 相同类型的bean的时候,会自动的注入到私有属性,如果容器里存在两个相同接口(类型的)bean 则会抛出异常

@autowired和@resource注解的区别?

  • @Autowired与@Resource都可以用来装配bean,都可以写在字段或setter方法上   
  • @Autowired默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false。如果想使用名称装配可以结合@Qualifier注解进行使用。   
  • @Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。   

推荐使用@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与Spring的耦合。

阅读剩余
THE END