一般情况下,控制层(controller)需要调用业务层(service)进行业务逻辑处理,业务层调用持久层(dao)访问数据库。这时候就需要使用自动装配注入相应的bean.在controller中注入service,在service中注入repository。
package com.spring.annotation.repository;
public interface UserRepository {
public void save();
}
package com.spring.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("UserRepository save...");
}
}
package com.spring.annotation.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.spring.annotation.repository.UserRepository;
@Service
public class UserService {
@Autowired(required=false)
private UserRepository userRepository;
public void save() {
System.out.println("UserService save...");
userRepository.save();
}
}
使用注解注入了userRepository,并且调用userRepository的save方法
package com.spring.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.spring.annotation.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void save() {
System.out.println("UserController save...");
userService.save();
}
}
使用注解注入了userService,并且调用userService的save方法
测试:
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserController uc = (UserController) ctx.getBean("userController");
uc.save();
如果被注入的bean没有在bean容器中注册,使用@Autowired注解就会报错。可以在@Autowired中设置required=false标识可以为null.
将@Autowired标识在setter方法上
package com.spring.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.spring.annotation.service.UserService;
@Controller
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void save() {
System.out.println("UserController save...");
userService.save();
}
}
这种写法和上面效果一样
- @Autowired是byType类型的
- 在使用@Autowired时,首先在容器中查询对应类型的bean 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
如果查询的结果不止一个,那么@Autowired会根据名称来查找。- 如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false,可以为null
当@Autowired匹配到多个相同类的bean时会自动转换成byName方式
下面就这种情况进行详细讲解:
下面是转化为byName方式后的运行情况
- @Autowired标识在属性上,根据属性名去bean容器匹配bean的id。匹配到就将之注入。
如:
UserRepositoryImpl 类
@Repository("user1Repository")
public class UserRepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("UserRepository save...");
}
}
User2RepositoryImpl 类
package com.spring.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository(user2Repository)
public class User2RepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("User2Repository save...");
}
}
定义了两个相同接口的类,一个注册为id = “user1Repository”的bean一个注册为id = “user2Repository”的bean.
注入:
@Autowired
private UserRepository user1Repository;
这里先按类型匹配,但是出现两个相同类型的,这时候就转换成按名称匹配。
这里属性名称为user1Repository,以byName方式匹配id = “use1Repository”的bean.
如:
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository user1Repository) {
this.userRepository = user1Repository;
}
这里的setter方法的参数名为user1Repository 可以匹配到bean.
@Autowired
@Qualifier("user1Repository")
private UserRepository userRepository;
这样就可以解放属性名,不用再使用属性名去匹配了。
使用@Qualifier注解后直接转换成byName方式
private UserRepository userRepository;
@Autowired
@Qualifier("user1Repository")
public void setUserRepository(UserRepository userRepository1) {
this.userRepository = userRepository1;
}
或者
@Autowired
public void setUserRepository(@Qualifier("user1Repository") UserRepository userRepository1) {
this.userRepository = userRepository1;
}
- @Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
- @Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
- @Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值
本系列参考视频教程: http://edu.51cto.com/course/1956.html