Spring的四种自动装配模式:No、byName、byType、constructor
自动转配就是类中的定义的其他的引用导致类与类中有了依赖关系,需要管理他们的依赖关系,Spring可以使用自动装配的方式,自动的依赖他们的关系。不用手动的建立依赖。
两种创建模式:一种是全局的、一种是在某一个Bean上进行指定
全局的:
<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"
default-autowire="byName"
>
在某一Bean上直接使用
<bean id="service" class="com.sevice.Service" autowire="byName"/>
no
就是没有自动装配,必须手动管理它们的依赖关系。
byName
使用名称一致的方式进行装配
例如:在XML文件中写了代码一的方式,那么需要在service中引入 dao这个类时需要使用相同的名字,如代码二 private Dao dao 高亮的部分
代码一
<bean id="dao" class="com.dao.daoImpl"/>
<bean id="service" class="com.sevice.Service" autowire="byName"/>
代码二
public class Service {
''' private Dao dao;'''
public void prient(){
dao.query();
}
public void setDao(Dao dao) {
this.dao = dao;
}
}
byType
使用类型一致的方式进行装配,就是找相同类型的类进行装配。
代码块一中装配时回去找代码块二中一致的代码。
代码块一
<bean id="dao" class="com.dao.daoImpl"/>
<bean id="service" class="com.sevice.Service" autowire="byType"/>
代码块二
public class Service {
private Dao dao;
public void prient(){
dao.query();
}
public void setDao(Dao dao) {
this.dao = dao;
}
}
会出现一中问题就是两个实现类同时对一个接口实现了,在依赖于这个接口的类中自动装配实现类时会找不到具体指定哪一个实现类。
例如
<bean id="dao" class="com.dao.daoImpl"/>
<bean id="dao2" class="com.dao.daoImpl2"/>
<bean id="service" class="com.sevice.Service" autowire="byType"/>
注意byType和byName都是使用的set注入的方式。还有一种的构造器注入
constructor
构造器注入的方式使用的是相同的名称来进行注入的。
代码一
<bean id="service" class="com.sevice.Service" autowire="constructor"/>
代码二
public class Service {
private Dao dao;
public Service(Dao dao) {
this.dao = dao;
}
public void prient(){
dao.query();
}
}
@Autowired
自动装配依赖还可以使用注解的方式,有Spring提供的 @Autowired注解和javax.annotation提供的@Resource
@Autowired放在属性上为Set注入,它首先会根据类型(byType)进行查找,如果找不到以名称(byName)进行查找。使用方式:
@Autowired
private Dao daoImpl;
若Dao只有一个实现类则按照Dao类型找出其相应的实现类,作为依赖的具体实现。若有两个实现类则Spring会将实现类的首字母变小写然后和引用变量进行比较从而找出一致的类。例如dao有两个实现类代码二和代码三
代码一
public interface Dao {
void query();
}
代码二
@Component
public class daoImpl implements Dao {
public void query() {
System.out.println("Impl");
}
}
代码三
@Component
public class daoImpl2 implements Dao {
public void query() {
System.out.println("Impl2");
}
}
如果写成代码四的方式引入依赖
@Service
public class ServiceImpl {
@Autowired
private Dao dao;
public void prient(){
dao.query();
}
}
则会报错
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'serviceImpl': Unsatisfied dependency expressed through field 'dao'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.dao.Dao' available: expected single matching bean but found 2: daoImpl,daoImpl2
在代码五中你只要定义一个和其中一个实现类名称相同即可
@Service
public class ServiceImpl {
@Autowired
private Dao daoImpl;
public void prient(){
daoImpl.query();
}
}
当然若只有一个实现类,则完全可以按照类型引入引用,而不用关注名称。
如果需要使用别名进行依赖注入的话需要使用@Qualifier(“dao2”)和@Autoaware一起使用。
@Resource
@Resource是javaAPI提供的注解,可以直接使用 @Resource(name = “dao2”)进行依赖注入,也可以不指定名称。使用的是类的的首字母小写生成的依赖名称进行查找注入,它会先找与定义依赖引用变量一致的,若找不到则会找相同类型的的类进行注入。
自动装配的优缺点
Autowiring has the following advantages:
Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.)
Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable.
Consider the limitations and disadvantages of autowiring:
Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
Autowiring is less exact than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
Wiring information may not be available to tools that may generate documentation from a Spring container.
Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Maps, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.
注:Spring在默认情况下会用单例模式将所有的Bean加载到容器中,如果开启懒加载也就是在用到的时候才加载的方式可以使用。设置懒加载的方式:
<bean id="service" class="com.sevice.ServiceImpl" autowire="constructor" lazy-init="true"/>