Spring组件扫描示例
在Spring XML配置示例中,我们看到了如何在XML中指定配置元数据,该元数据用于注册bean和连接依赖项。 Spring框架还提供了自动发现bean和自动关联依赖项的选项,在这个Spring组件扫描示例中,我们将看到如何完成此操作。
Spring组件扫描
通过使用组件扫描,Spring框架通过扫描类路径自动检测Bean类,并在容器中注册Bean定义。这消除了使用XML进行bean注册的需要,并使XML保持最低限度(或者可以使用Java配置)。
为了隐式检测bean,可以在要向容器中注册bean定义的类上使用@Component注释。请注意,@Component是任何Spring托管组件的通用构造型。 @ Repository,@ Service和@Controller是@Component的特化,用于更特定的用例。
@Repository –持久层类
@Service –服务层类
@Controller –表示层类。
bean的自动发现和自动装配
要在Spring中进行自动配置,我们需要注意两点:
组件扫描-正如已经通过使用组件扫描对Bean进行自动检测并在应用程序上下文中注册Bean定义所说明的那样,此操作由Spring框架完成。使用XML配置时,我们只需要将<context:component-scan>元素与基本软件包一起使用,以提供要扫描的软件包中的组件。在基于Spring Java的配置中,我们可以使用@ComponentScan注释来启用组件扫描。
自动接线–自动注入依赖项,为此使用@Autowired注释。
Spring Component扫描示例
在示例中,有两个可发现的Bean EmployeeService和EmployeeDAO。在EmployeeService类中,使用@Service注释,而在EmployeeDAO类中使用@Repository注释。这些注释的使用使这些类在完成组件扫描时就有资格进行扫描。
public class Employee {
int empId;
String empName;
String dept;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Id= " + getEmpId() + " Name= " +
getEmpName() + " Dept= "+ getDept();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.theitroad.springproject.dao.EmployeeDAO;
import com.theitroad.springproject.model.Employee;
@Service
public class EmployeeService {
// Dependency
@Autowired
EmployeeDAO employeeDAO;
public Employee getEmployee() {
return employeeDAO.findEmployee();
}
}
import org.springframework.stereotype.Repository;
import com.theitroad.springproject.model.Employee;
@Repository
public class EmployeeDAO {
public Employee findEmployee() {
return getEmployee();
}
// Stub method for getting Employee info
private Employee getEmployee() {
Employee emp = new Employee();
emp.setEmpId(1);
emp.setEmpName("Joe Marshal");
emp.setDept("Finance");
return emp;
}
}
EmployeeService类具有对EmployeeDAO的依赖关系,该依赖关系会自动满足,这就是为什么@Autowired注释与employeeDAO属性一起使用的原因。
使用<context:component-scan />元素进行组件扫描– XML配置
<?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.xsd">
<context:component-scan base-package="com.theitroad.springproject.service,
com.theitroad.springproject.dao"/>
</beans>
使用Bean类所在的基本软件包属性软件包指定为逗号分隔的列表。
我们可以将以下类与main方法一起使用以读取配置并调用bean方法。默认情况下,通过小写类名的第一个字母,从类派生给ID的ID,因此EmployeeService类的bean ID是employeeService。
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.theitroad.springproject.model.Employee;
import com.theitroad.springproject.service.EmployeeService;
public class App {
public static void main( String[] args ){
// create context using configuration
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
EmployeeService employeeService = context.getBean("employeeService", EmployeeService.class);
Employee emp = employeeService.getEmployee();
System.out.println("Employee- " + emp);
// close the context
context.close();
}
}
输出:
11:39:00.431 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 6 bean definitions from class path resource [appcontext.xml] 11:39:00.481 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' 11:39:00.657 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' 11:39:00.666 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' 11:39:00.674 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' 11:39:00.698 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'employeeService' 11:39:00.873 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'employeeDAO' Employee- Id= 1 Name= Joe Marshal Dept= Finance
使用Spring @ComponentScan注释启用组件扫描
如果要使用Java配置,则需要以下类。
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages= {"com.theitroad.springproject.service",
"com.theitroad.springproject.dao"})
public class AppConfig {
}
为了运行该应用程序,我们可以使用以下类。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import com.theitroad.springproject.model.Employee;
import com.theitroad.springproject.service.EmployeeService;
public class App {
public static void main( String[] args ){
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
EmployeeService employeeService = context.getBean("employeeService", EmployeeService.class);
Employee emp = employeeService.getEmployee();
System.out.println("Employee- " + emp);
context.close();
}
}
现在,AnnotationConfigApplicationContext用于创建将JavaConfig类作为输入的Spring应用程序上下文。
使用过滤器自定义组件扫描
通过应用排除和包含过滤器,我们可以指定要检测的组件。使用Java配置时,可以将它们添加为@ComponentScan注释的includeFilters或者excludeFilters参数,使用XML时,可以将其添加为component-scan元素的include-filter或者exclude-filter子元素。
例如,如果要在Service软件包中包括类,并且要从组件扫描中排除DAO软件包中的类。
使用@ComponentScan
@ComponentScan(basePackages= {"com.theitroad.springproject.service",
"com.theitroad.springproject.dao"}, includeFilters = @Filter(type = FilterType.REGEX, pattern ="com.theitroad.springproject.service..*"),
excludeFilters = @Filter(type = FilterType.REGEX, pattern ="com.theitroad.springproject.dao..*"))
使用<context:component-scan />
<context:component-scan base-package="com.theitroad.springproject.service, com.theitroad.springproject.dao"> <context:include-filter type="regex" expression="com\.theitroad\.springproject\.service\..*"/> <context:exclude-filter type="regex" expression="com.theitroad.springproject.dao..*"/> </context:component-scan>

