使用组件扫描的方式可以让Spring从classpath下自动扫描,侦测和实例化具有特定注解的组件。这些注解分别是:
@Component:基本注解,标识一个受Spring管理的组件
@Respository:标识持久层组件
@Service:标记服务层(业务层)组件
@Controller:标识表示层组件
这些注解是建议大家在对应的层使用对应的组件,但实际上全部使用Component也没报错
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,我们也可以在注解中通过value属性标识组件的名称
用一个简单的例子来展示一下:
1.表示层组件
package annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import annotation.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void execute() {
System.out.println("USerControllor excute...");
userService.add();
}
}
2.服务层组件
package annotation.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import annotation.repository.UserRepository;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
//Autowire可以放在变量前也可以放在方法前
//@Autowired
//public void setUserRepository(UserRepository userRepository) {
// this.userRepository = userRepository;
//}
public void add() {
System.out.println("USerService add...");
userRepository.save();
}
}
3.持久层组件
package annotation.repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("UserRepository Save..");
}
}
4.在bean的配置文件中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 指定spring IOC容器扫描的包 -->
<context:component-scan base-package="annotation" ></context:component-scan>
</beans>
5,用main函数测试一下
package annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import annotation.controller.UserController;
import annotation.repository.UserRepository;
import annotation.service.UserService;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserController userController = (UserController)ctx.getBean("userController");
System.out.println(userController);
userController.execute();
}
}
在控制台上输出了以下内容:
annotation.controller.UserController@157696f
USerControllor excute...
USerService add...
UserRepository Save..
如果UserRepository是一个接口类,而且有多个实现类的话,应该怎么破呢?
让我们来试一试看看会出什么事
package annotation.repository;
public interface UserRepository {
void save();
}
再写两个实现类
package annotation.repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepositoryImpl implements UserRepository {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("UserRepository Save..");
}
}
package annotation.repository;
import org.springframework.stereotype.Repository;
@Repository
public class UserJdbcRepository implements UserRepository {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("UserJdbcRepository save..");
}
}
再次运行上面的main函数会发现报错了
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [annotation.repository.UserRepository] is defined: expected single matching bean but found 2: userJdbcRepository,userRepositoryImpl
它说没有唯一的实现类,为了解决这个问题,我们可以在UserService中指定用哪个类来实例化bean
package annotation.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import annotation.repository.UserRepository;
@Service
public class UserService {
@Autowired
//声明使用指定的类来实例化bean
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;
//Autowire可以放在变量前也可以放在方法前
//@Autowired
//@Qualifier("userRepositoryImpl")
//public void setUserRepository(UserRepository userRepository) {
// this.userRepository = userRepository;
//}
public void add() {
System.out.println("USerService add...");
userRepository.save();
}
}
再次运行就可以发现没问题了
在Autowire中设置required=fasle可以让Spring在没找到对应的bean时不进行报错,这里就不展示了