Spring组件扫描示例

时间:2020-01-09 10:44:32  来源:igfitidea点击:

在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>