Spring @Autowired Annotation

 

Spring @Autowired Annotation

 

Spring @Autowired注释用于自动依赖注入。Spring框架是基于依赖注入构建的,我们通过spring bean配置文件注入类依赖项。

目录[ 隐藏 ]

  • 1 Spring @Autowired Annotation
    • 1.1 Spring @Autowired Annotation - Maven依赖项
    • 1.2 Spring @Autowired Annotation - Model Bean
    • 1.3 Spring @Autowired Annotation - 服务类
    • 1.4 Spring @Autowired Annotation - 自动装配byType示例
    • 1.5 Spring @Autowired Annotation和@Qualifier Bean通过构造函数自动装配示例
    • 1.6 Spring @Autowired Annotation - Bean配置文件
    • 1.7 Spring @Autowired Annotation - 测试程序

Spring @Autowired Annotation

Spring @Autowired Annotation_第1张图片

通常我们在spring bean配置文件中提供bean配置细节,并且我们还使用refattribute 指定将在其他bean中注入的bean 。但Spring框架也提供了自动装配功能,我们不需要明确提供bean注入细节。

我们可以通过不同的方式自动装配一个spring bean。

  1. autowire byName - 对于这种类型的自动装配,setter方法用于依赖注入。此外,变量名应该在我们将注入依赖项的类中和spring bean配置文件中相同。
  2. autowire byType - 对于这种类型的自动装配,使用类类型。因此,spring bean配置文件中只应该为此类型配置一个bean。
  3. autowire by constructor - 这几乎类似于autowire byType,唯一的区别是构造函数用于注入依赖项。
  4. autodeire by autodetect - 如果你使用的是Spring 3.0或更早版本,这是可用的autowire选项之一。此选项由构造函数或byType用于autowire,由Spring容器确定。由于我们已经有这么多选项,因此不推荐使用此选项。我不会在本教程中介绍此选项。
  5. @Autowired注释 - 我们可以使用Spring @Autowired注释进行spring bean自动装配。@Autowired注释可以应用于自动装配byType的变量和方法。我们还可以在构造函数上使用@Autowired注释来构造基于Spring的自动装配。

    要使@Autowired注释起作用,我们还需要在spring bean配置文件中启用基于注释的配置。这可以通过context:annotation-config元素或通过定义类型的bean来完成org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

  6. @Qualifierannotation - 此注释用于避免bean映射中的冲突,我们需要提供将用于自动装配的bean名称。这样我们就可以避免为同一类型定义多个bean的问题。此注释通常与@Autowired注释一起使用。对于具有多个参数的构造函数,我们可以将此注释与方法中的参数名称一起使用。

默认情况下,Spring bean自动装配已关闭。Spring bean autowire默认值为“default”,表示不执行自动装配。autowire值“no”也有相同的行为。

为了展示Spring Bean自动装配的使用,让我们创建一个简单的Spring Maven项目。我们的最终项目将如下图所示。

 

Spring @Autowired Annotation_第2张图片

让我们逐个研究每个autowire选项。为此,我们将创建一个Model bean和一个服务类,我们将在其中注入模型bean。

Spring @Autowired Annotation - Maven Dependencies

对于spring自动装配,我们不需要添加任何其他依赖项。我们的pom.xml文件具有spring框架核心依赖关系,如下所示。


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<groupId>org.springframework.samplesgroupId>
	<artifactId>SpringBeanAutowiringartifactId>
	<version>0.0.1-SNAPSHOTversion>

	<properties>

		
		<java.version>1.6java.version>
		<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>

		
		<spring-framework.version>4.0.2.RELEASEspring-framework.version>

		
		<logback.version>1.0.13logback.version>
		<slf4j.version>1.7.5slf4j.version>

	properties>

	<dependencies>
		
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-contextartifactId>
			<version>${spring-framework.version}version>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-txartifactId>
			<version>${spring-framework.version}version>
		dependency>

		
		<dependency>
			<groupId>org.slf4jgroupId>
			<artifactId>slf4j-apiartifactId>
			<version>${slf4j.version}version>
			<scope>compilescope>
		dependency>
		<dependency>
			<groupId>ch.qos.logbackgroupId>
			<artifactId>logback-classicartifactId>
			<version>${logback.version}version>
			<scope>runtimescope>
		dependency>

	dependencies>
project>

Spring @Autowired Annotation - Model Bean

让我们创建一个名为Employee的简单Java Bean。这个bean将有一个带getter和setter方法的属性。我们将在spring bean配置文件中初始化此属性值。


package com.journaldev.spring.autowiring.model;

public class Employee {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Spring @Autowired Annotation - 服务类

让我们创建我们的服务类,我们将通过spring自动装配注入Employee bean。


package com.journaldev.spring.autowiring.service;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeService {

	private Employee employee;

	// constructor is used for autowire by constructor
	public EmployeeService(Employee emp) {
		System.out.println("Autowiring by constructor used");
		this.employee = emp;
	}

	// default constructor to avoid BeanInstantiationException for autowire
	// byName or byType
	public EmployeeService() {
		System.out.println("Default Constructor used");
	}

	// used for autowire byName and byType
	public void setEmployee(Employee emp) {
		this.employee = emp;
	}

	public Employee getEmployee() {
		return this.employee;
	}
}

我们将使用相同的服务类来执行Spring自动装配byName,byType和构造函数。setter方法将用于弹簧自动装配byName和byType,而基于构造函数的注入将由构造函数autowire属性使用。

当我们使用spring autowire byName或byType时,使用默认构造函数。这就是我们为EmployeeService bean明确定义默认构造函数的原因。

Spring @Autowired Annotation - 自动装配byType示例

让我们用Spring @Autowired注释创建一个单独的类,用于自动装配byType。


package com.journaldev.spring.autowiring.service;

import org.springframework.beans.factory.annotation.Autowired;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeAutowiredByTypeService {

	//Autowired annotation on variable/setters is equivalent to autowire="byType"
	@Autowired
	private Employee employee;
	
	@Autowired
	public void setEmployee(Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee(){
		return this.employee;
	}
}

请注意,我已经使用Spring @Autowired注释注释了Employee变量和它的setter方法,但是只有其中一个足以用于spring bean自动装配。

Spring @Autowired Annotation和@Qualifier Bean通过构造函数自动装配示例

让我们创建另一个服务类,我们将使用@Autowired注释进行基于构造函数的注入。我们还将看到@Qualifier注释用法。


package com.journaldev.spring.autowiring.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeAutowiredByConstructorService {

	private Employee employee;

	//Autowired annotation on Constructor is equivalent to autowire="constructor"
	@Autowired(required=false)
	public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee() {
		return this.employee;
	}
}

当这个bean将被Spring框架初始化时,名为“employee”的bean将用于自动装配。Spring @Autowired注释除了一个参数“required”,它是一个布尔值,默认值为TRUE。我们可以将它定义为“false”,这样如果找不到适合自动装配的bean,spring框架就不会抛出任何异常。

Spring @Autowired Annotation - Bean配置文件

Spring bean配置文件是任何spring应用程序的主要部分,让我们看一下spring 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.0.xsd"
		
		default-autowire="byName" default-autowire-candidates="*" >

<bean name="employee" class="com.journaldev.spring.autowiring.model.Employee">
	<property name="name" value="Pankaj">property>
bean>

<bean name="employee1" class="com.journaldev.spring.autowiring.model.Employee" autowire-candidate="false">
	<property name="name" value="Dummy Name">property>
bean>


<bean name="employeeServiceByName" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="byName" />


<bean name="employeeServiceByType" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="byType" />


<bean name="employeeServiceConstructor" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="constructor" />


<context:annotation-config />


<bean name="employeeAutowiredByTypeService" class="com.journaldev.spring.autowiring.service.EmployeeAutowiredByTypeService" />
<bean name="employeeAutowiredByConstructorService" class="com.journaldev.spring.autowiring.service.EmployeeAutowiredByConstructorService" />
beans>

关于spring bean配置文件的重点是:

  • beans元素default-autowire用于定义默认的自动装配方法。在这里,我将默认的自动装配方法定义为byName。
  • beans元素default-autowire-candidates用于为可用于自动装配的bean名称提供模式。为简单起见,我允许所有bean定义都符合自动装配的条件,但是如果我们可以为自动装配定义一些模式。例如,如果我们只想要自动装配DAO bean定义,我们可以将其指定为default-autowire-candidates="*DAO"
  • autowire-candidate="false"用于bean定义,使其不符合自动装配的条件。当我们为单个类型提供多个bean定义时,它们很有用,我们希望其中一些不是自动装配的。例如,在上面的spring bean配置中,“employee1”bean不会用于自动装配。
  • autowire属性byName,byType和构造函数是自我理解的,没什么可解释的。
  • context:annotation-config用于启用基于注释的配置支持。请注意,employeeAutowiredByTypeService和employeeAutowiredByConstructorService bean没有autowire属性。

Spring @Autowired Annotation - 测试程序

既然我们的弹簧应用已经准备好了所有类型的弹簧自动装配,那么让我们编写一个简单的测试程序,看看它是否按预期工作。


package com.journaldev.spring.autowiring.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.journaldev.spring.autowiring.service.EmployeeAutowiredByConstructorService;
import com.journaldev.spring.autowiring.service.EmployeeAutowiredByTypeService;
import com.journaldev.spring.autowiring.service.EmployeeService;

public class SpringMain {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
		
		EmployeeService serviceByName = ctx.getBean("employeeServiceByName", EmployeeService.class);
		
		System.out.println("Autowiring byName. Employee Name="+serviceByName.getEmployee().getName());
		
		EmployeeService serviceByType = ctx.getBean("employeeServiceByType", EmployeeService.class);
		
		System.out.println("Autowiring byType. Employee Name="+serviceByType.getEmployee().getName());
		
		EmployeeService serviceByConstructor = ctx.getBean("employeeServiceConstructor", EmployeeService.class);
		
		System.out.println("Autowiring by Constructor. Employee Name="+serviceByConstructor.getEmployee().getName());
		
		//printing hashcode to confirm all the objects are of different type
		System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
		
		//Testing @Autowired annotations
		EmployeeAutowiredByTypeService autowiredByTypeService = ctx.getBean("employeeAutowiredByTypeService",EmployeeAutowiredByTypeService.class);
		
		System.out.println("@Autowired byType. Employee Name="+autowiredByTypeService.getEmployee().getName());

		EmployeeAutowiredByConstructorService autowiredByConstructorService = ctx.getBean("employeeAutowiredByConstructorService",EmployeeAutowiredByConstructorService.class);
		
		System.out.println("@Autowired by Constructor. Employee Name="+autowiredByConstructorService.getEmployee().getName());

		ctx.close();
	}
}

程序很简单,我们只是创建spring应用程序上下文并使用它来获取不同的bean并打印员工姓名。

当我们运行上面的应用程序时,我们得到以下输出


Mar 31, 2014 10:41:58 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Mon Mar 31 22:41:58 PDT 2014]; root of context hierarchy
Mar 31, 2014 10:41:58 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Default Constructor used
Default Constructor used
Autowiring by constructor used
Autowiring byName. Employee Name=Pankaj
Autowiring byType. Employee Name=Pankaj
Autowiring by Constructor. Employee Name=Pankaj
21594592::15571401::1863015320
@Autowired byType. Employee Name=Pankaj
@Autowired by Constructor. Employee Name=Pankaj
Mar 31, 2014 10:41:58 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Mon Mar 31 22:41:58 PDT 2014]; root of context hierarchy

正如您所看到的,对于autowire byName和byType,默认的no-args构造函数用于初始化bean。对于构造函数的autowire,使用基于参数的构造函数。

从所有变量的哈希码,我们已经确认所有的spring bean都是不同的对象,而不是指同一个对象。

由于我们从符合条件的bean列表中删除了“employee1”以进行自动装配,因此bean映射中没有混淆。如果我们autowire-candidate="false"从“employee1”定义中删除,我们将在执行上述main方法时得到以下错误消息。


Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employeeServiceByType' defined in class path resource [spring.xml]: Unsatisfied dependency expressed through bean property 'employee': : No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1278)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1170)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
	at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
	at com.journaldev.spring.autowiring.main.SpringMain.main(SpringMain.java:12)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1263)
	... 13 more

这就是Spring @Autowired Annotation和Spring自动装配功能的全部内容,请从下面链接下载示例项目并进行分析以了解更多信息。

 

你可能感兴趣的:(Unix&Unix-Like,Java,Spring)