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>