在项目中遇到这么一个困惑
在controller层自动装配了一个service的接口
@Resource
ProjectService projectService;
为什么可以直接使用接口实现类重写的方法?
public List<PostProject> getProjectList(String projectName, String projectStatus){
return projectService.getProjectList(projectName,projectStatus);
}
ProjectService.java
public interface ProjectService {
List<PostProject> getProjectList(String projectName, String projectStatus);
}
ProjectServiceImpl.java
@Service
public class ProjectServiceImpl implements ProjectService{
@Override
public List<PostProject> getProjectList(String projectName, String projectStatus) {
...
return postProjectList;
}
}
@service
接口实现类上的@service
注解等价于
xml配置文件上的<bean id="projectServiceImpl" class="service.ProjectServiceImpl"/>
上述配置等价于
<!--在Spring中创建对象,在Spring这些都称为bean
类型 变量名 = new 类型();
Holle holle = new Holle();
bean = 对象(holle)
id = 变量名(holle)
class = new的对象(new Holle();)
property 相当于给对象中的属性设值,让str="Spring"
-->
<bean id="hello" class="pojo.Hello">
<property name="str" value="Spring"/>
</bean>
controller层上的
@Resource
ProjectService projectService;
下面先来了解一下@Autowired
和@Resource
@Autowired
@Autowired
为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired。
@Autowired
采取的策略为按照类型注入。
public class UserService {
@Autowired
private UserDao userDao;
}
如上代码所示,这样装配会去spring容器中找到类型为UserDao的类,然后将其注入进来。这样会产生一个问题,当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候我们需要配合着@Qualifier
使用。
@Qualifier
告诉spring具体去装配哪个对象。
public class UserService {
@Autowired
@Qualifier(name="userDao1")
private UserDao userDao;
}
这个时候我们就可以通过类型和名称定位到我们想注入的对象
@Resource
@Resource
注解由J2EE提供,需要导入包javax.annotation.Resource。
@Resource
默认按照ByName自动注入。
public class UserService {
@Resource
private UserDao userDao;
@Resource(name="studentDao")
private StudentDao studentDao;
@Resource(type="TeacherDao")
private TeacherDao teacherDao;
@Resource(name="manDao",type="ManDao")
private ManDao manDao;
}
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配(当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配);如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
推荐使用:@Resource
注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。
针对不用写setter方法的理解,看下面
//在Service层的实现类(UserServiceImpl)增加一个Set()方法
//利用set动态实现值的注入!
//DAO层并不写死固定调用哪一个UserDao的实现类
//而是通过Service层调用方法设置实现类!
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
((UserServiceImpl)userService).setUserDao(new UserDaoImpl());
set方法中的参数为接口,传入的参数为接口的实现(类似代理模式)
自己的理解:@Resource标注在ProjectService接口上,取属性名(projectService)进行装配,没有找到(@Service标注的ProjectServiceImpl默认名字是projectServiceImpl),再找相同类型的,找到ProjectServiceImpl(这里是通过多态的向上转型的方式判定ProjectServiceImpl和其接口的类型一样,所以虽然我们定义的属性是接口类型的,但是最终时候会装配到实现类上),实现自动装配
参考文章:
https://blog.csdn.net/weixin_40423597/article/details/80643990