`
DynamicMan
  • 浏览: 25465 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

4.基于注解的bean装配

 
阅读更多

        对于spring提供传统XML配置方式来说,由于项目的日益扩大,XML配置信息也会随之增加,对于项目的后期管理和维护造成一定的复杂性,为了减少XML配置信息,spring提供了基于注解的配置。

        spring提供了自动装配和自动检测功能,用于减少XML配置信息。

 

spring的自动装配4种策略

byName

根据名字进行自动装配,改名字为spring配置中的id名,如果没有找到对应的id名则不进行装配

byType 根据bean的属性相同类型的其他bean进行自动装配,如果没有找到相同类型的其他bean,则不进行装配
constructor 把与bean的构造器入参具有相同类型的其他bean自动装配到bean的构造器对应入参中
autodetect 首先尝试constructor进行自动装配,如果失败,则尝试byType进行自动装配

 

byName实现自动装配:    

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		   http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
         
    <bean id="robbie" class="org.robbie.test.spring.beans.Robbie" autowire="byName" />
    <bean id="flute" class="org.robbie.test.spring.beans.Flute" />
	
</beans>

 在这里配置的两个bean中,由于robbie中的一个属性命名为flute,并且配置了autowire属性为byName,那么则会把当前在spring容器当中id为flute的bean自动装配进来,如果当前多个bean中都有名称为flute的属性,则都会将同一个flute bean装配进来

 

 

byType实现自动装配:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		   http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
         
    <bean id="robbie" class="org.robbie.test.spring.beans.Robbie" autowire="byType" />
    <bean id="flute1" class="org.robbie.test.spring.beans.Flute" />
	
</beans>

 当前装配采用byType,因为robbie这个bean里面的属性有一个类型为Instrument的属性,而Flute类也实现了此接口,所以会自动将id为flute1的bean注入到robbie的属性当中。该例中要注意一个问题,如果在装配中在spring容器中发现了有多个相同类型的bean,该注入哪一个bean呢,通常来说spring遇到这种情况会直接抛出异常。为了避免类型相同进行装配的歧义,spring有两种解决方案:

1.自动装配标识一个首选bean;2.取消某个bean的自动装配候选资格

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		   http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
         
    <bean id="robbie" class="org.robbie.test.spring.beans.Robbie" autowire="byType" />
    <bean id="flute" class="org.robbie.test.spring.beans.Flute" />
    <bean id="piano" class="org.robbie.test.spring.beans.Piano" primary="false" />
	
</beans>

 配置primary属性为false(默认为true),降低优先级,当发现两个相同类型的bean时,选择优先级高的进行注入,此例中将会注入flute

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		   http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
         
  <bean id="robbie" class="org.robbie.test.spring.beans.Robbie" autowire="byType" />
  <bean id="flute" class="org.robbie.test.spring.beans.Flute" />
  <bean id="piano" class="org.robbie.test.spring.beans.Piano" autowire-candidate="false" />
	
</beans>

 配置autowire-candidate属性为false(默认为true),取消自动注入候选资格,该例中将会注入id为flute的bean

 

 

constructor自动装配:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		   http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
         
    <bean id="robbie" class="org.robbie.test.spring.beans.Robbie" autowire="constructor" />
    <bean id="flute" class="org.robbie.test.spring.beans.Flute" />
	
</beans>

 配置属性autowire为constructor,此例中spring将会检查robbie的构造器,查找构造器当中的参数类型是否与当前容器当中的bean类型相互匹配,如果匹配则通过构造器进行注入,当前例子中因为robbie的构造器中有一个形参为Flute类型的参数,则自动会将flute进行注入

 

 

如果配置autowire为autodetect将会进行自动选择进行装配,首先尝试constructor,如果失败尝试byType,此配置在3.0后已经被废弃。

 

如果需要用到全局配置自动装备属性,则在根元素beans配置defaul-autowire,例如:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		   http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-3.0.xsd"
           default-autowire-candidates="false" default-autowire="byType">
	
</beans>

此例中配置了全局的default-autowire-candidates为false,并且default-autowire为byType,意思当前在此配置文件中应用的所有bean取消自动装配候选资格,并且按照byType进行自动装配。对于bean中配置的autowire属性将会覆盖全局默认配置的default-autowire属性的值,从而达到个性化。

注意:当使用constructor自动装配时,不能配置constructor-arg属性,因为spring会自动去填充对应的constructor的参数,手动再去配置constructor-arg会引起冲突,从而报错。但是如果是其他类型的自动装配,可以显示的进行设值,即手工装配和自动装配进行混合使用,首先会使用手动注入的配置

 

基于注解的装配

        spring默认是禁止了注解的装配的,一旦使用了注解装配,那么在XML上就可以把配置property的地方去掉了,要启动它必须进行显示开启:

添加命名空间:

 

xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
 增加配置:

 

 

<context:annotation-config />
 spring支持3种自动装配的注解:

 

spring自带的@Autowired注解
JSR-330的@Inject注解
JSR-250的@Resource注解

 

使用@Autowired

 

package org.robbie.test.spring.beans;

import org.robbie.test.spring.exception.PerformerException;
import org.robbie.test.spring.inf.Performer;
import org.robbie.test.spring.inf.Poem;
import org.springframework.beans.factory.annotation.Autowired;

public class Juggler implements Performer {
	
	@Autowired
	private Poem poem;

	private int beanBags = 3;
	
	@Autowired
	public void setBeanBags(int beanBags) {
		this.beanBags = beanBags;
	}
	
	
	public static String name = "juggler";
	
	public Juggler() {
	}
	
	public Juggler(int beanBags) {
		this.beanBags = beanBags;
	}

	public Juggler(int beanBags, Poem poem) {
		this.beanBags = beanBags;
		this.poem = poem;
	}
	
	public static String name(){
		return "jugglerMethod";
	}
	
	public String method() {
		return "AA";
	}

	@Override
	public void perform() throws PerformerException {
		System.out.println("Juggling " + beanBags + " Beanbags");
		poem.recite();
	}

	public int getBeanBags() {
		return beanBags;
	}

}
 该例中,@Autowired可以配置在属性上,也可以配置在方法上,都标识着自动装配对应的类型bean或值到属性当中,如果配置在方法上可以标注在构造方法或者任意方法上,如:

 

 

@Autowired
public Juggler(Poem poem) {
        this.poem = poem;
}
 
@Autowired
public void hereIsPoem(Poem poem){
        this.poem = poem;
}
@Autowired的注解不会受限于访问修饰符,即便是private依然可以完成注入的工作,并且如果当前容器存在多个类型(没有通过名字区分或者限定器限定)或者找不到匹配的类型来完成注入,就会出现错误,spring用以下两种方式进行解决:
@Autowired(required=false)
private Poem poem;
 标识poem属性的注入并不是必须的,如果找不到匹配的类型,则不进行注入
注意:如果@Autowired配置在多个构造器上,那么只有一个构造器可以配置为required为true,其他必须为false,并且spring会选择形参最多的构造器进行注入

 

 使用@Qualifier来限制歧义:

 

@Autowired()
@Qualifier("robbie")
private Poem poem;
 当spring容器中有两个或以上Poem类型bean时,会了选择特定的一个来进行注入,使用@Qualifier注解进行标注,此例中明确限定了id为robbie的poem进行注入,实际上使用@Qualifer大大的缩小了注入搜寻的范围,进行了一层注入前的过滤。@Qualifier还可以直接配置在类级别上,直接用于字符串标识bean:

 

 

@Qualifier("robbie")
public class Robbie implements Poem {

}
 同等的XML配置:

 

 

<bean id="robbie" class="org.robbie.test.spring.beans.Robbie">
        <qualifier value="robbie" />
</bean>
 当spring容器当中有两个以上Poem类型bean时,可以在需要注入的地方使用@Qualifier然后指定已经标识好字符串的bean,用于消除歧义,过滤多个相同类型的bean

 

 

创建自定义的限定器:

 

package org.robbie.test.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

@Target({ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyQualifier {

}
 将自定义的限定器用于自己建立的类上:
@MyQualifier
public class Robbie implements Poem {

}
 在注入的时候通过自定义的限定器进行过滤,缩小注入搜寻范围:

 

 

@Autowired
@MyQualifier
private Poem poem;
 此例中如果有多个Poem类型bean,那么注入的时候将会使用通过自定义限定器注解后的bean

 

 

总结:使用@Autowired注解来进行自动装配,在一定程度会上依赖spring框架(个人认为不是什么问题,开发中必须采用spring已经成为铁打的事实),所以也可以通过@Inject这个java标准自动装配注解来完成相同的工作。

 

使用@Inject:

        为了统一依赖注入的编程模型,JCP发布了依赖注入的规范,即JSR-330,spring已经兼容了此模型,@Inject可以完全替代@Autowired,但是也存在着一些区别,使用@Inject没有required属性,说明了在使用该注解时,必须要求注入,如果没有找到对应的类型bean或值,则会出现错误。

使用Provider进行延迟注入:

 

@Inject
public Juggler(Provider<Poem> provider){
        Poem poem = provider.get();
        poem.recite();
}
 该例中,Juggler的构造器并没有注入一个Poem,而是注入的Provider,使用Provider的get()方法,可以取得Poem对象,自行进行处理后,最后自行进行注入。

 

 

使用@Named限定@Inject的注入,@Named的用法跟@Qualifier的用法一致,自定义限定器也与@Qualifier一致:

 

@Inject
@Named("robbie")
private Poem poem;
 

 

在注解中应用表达式:

spring3.0后引入了@Value注解,可以装配基本类型和String类型的值,并且还能够在Value中使用表达式进行运算:

 

@Value("my name is robbie")
private String name; 

 

使用@Value装配硬编码的值其实并不是特别的有意义,该注解配合SpEL共同使用才能够真正起到实质性的作用,从而满足某些项目的依赖注入需求:

 

@Value("#{juggler.method()}")
private String name;
该例中会调动spring容器中juggler bean的method方法,将返回值注入到name属性当中。

 

 

@Resource注解使用:

使用@Resource注解跟前两者相同,不同的是自动装配时候的策略,该注解首先会根据名称进行匹配,如果没有找到再根据类型进行匹配,其他用法不再详述(@Autowired是先ByType查找,然后ByName)。

 

总结:自动装配能够让spring自动识别如何将bean装配到一起,从而减少XML配置,在bean的声明真正的独立起来(因为只关注如何声明bean,不会关注属性的注入问题),让解耦达到了一个新的高度。

 

bean的自动检测:

之前所配置的:

<context:annotation-config />
 消除了property和constructor-arg的XML配置,但是仍然需要在XML上定义bean,为了完全消除bean的定义,我们可以使用context:component-scan,该配置不仅能够完成context:annotation-config的工作,还能够自动检测定义的bean:

 

 

<context:component-scan base-package="org.robbie.test" />
 该例中会自动扫描org.robbie.test包下被注解应用的类,并将这些类放入spring容器形成bean

 

spring会扫描特定注解的类,这些注解如下:

@Component 通用注解,标识为spring组件
@Controller 标识定义为spring MVC的controller
@Repository

标识该类定义为数据仓库,一般为持久层

@Service 标识为服务

 

@Component
public class Robbie implements Poem {

}

 

也可以指定具体的名称,如果没有指定名称采用类名(首字母小写),来进行注册

@Component("name")
public class Robbie implements Poem {

}

 

过滤组件扫描:

<context:component-scan base-package="org.robbie.test" >
  <context:include-filter type="regex" expression="*Service"/>
  <context:exclude-filter type="annotation" expression="org.robbie.test.spring.MyQualifier"/>
</context:component-scan>

 过滤组件扫描的核心在于include-filter,exclude-filter配置,并且通过type和expression两个属性共同来指定扫描策略,include-filter是需要扫描的类,exclude-filter是不需要扫描的类。type为过滤器类型和expression为描述,说明如下:

过滤器类型 描述
annotation 过滤器扫描使用指定注解所标注的那些类,通过expression属性指定要扫描的注解
assignable 过滤器扫描继承于expression属性所指定类型的那些类
aspectj 过滤器扫描与expression属性所指定的Aspectj表达式所匹配的那些类
custom 使用自定义的org.springframework.core.type.TypeFilter的实现类,该类由expression属性指定
regex 过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的那些类

该例中扫描名称为Service结尾的类(通过正则表达式进行匹配),并排除了使用MyQualifier注解的类

 

基于JAVA的配置:

定义配置类:

 

package org.robbie.test.spring.beans;

import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

}

 @Configuration会告知spring,此类是一个配置类,这个类将包含一个或者多个spring bean的定义,这些bean的定义是使用@Bean注解所标注的方法:

package org.robbie.test.spring.beans;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

	
	@Bean
	public Object getObject(){
		return new Object();
	}
	
}

 该例中getObject方法返回的值将会作为spring的bean,通过基于JAVA的spring配置的好处是编译时期的检查,如果是在XML上都是通过字符串进行定义和描述,难免会出现错误,而JAVA的方法名为spring的ID名称,并且所有配置采用JAVA代码编写,在编译时期可以进行检测,降低出现错误的几率

在基于java配置的类中进行装配:

package org.robbie.test.spring.beans;

import org.robbie.test.spring.inf.Performer;
import org.robbie.test.spring.inf.Poem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {
	@Bean
	public Poem poem(){
		return new Robbie();
	}
	
	@Bean
	public Performer performer(){
		return new Juggler(poem());
	}
	
}

 注意:在该例中,配置类MyConfiguration里定义了两个bean,performer依赖poem,把poem作为bean通过构造器进行注入,实际上这里调用poem方法并不是每次都会去产生一个poem实例,spring在此做了拦截,它会去容器中查找poem实例,如果找到直接返回作为参数传递给performer,最后完成注入。

 

 

分享到:
评论

相关推荐

    spring3.x注解

    使用 @Autowired 注解时,Spring 容器将抛出异常如果找不到匹配的 Bean 或者存在多个匹配的 Bean。 使用 @Qualifier 注释可以指定注入 Bean 的名称,从而改变自动注入的策略。 2. @Resource @Resource 注解的作用...

    Spring4--2.bean注解和AOP

    3. `@Autowired`:这个注解用于自动装配Bean的依赖。Spring会根据类型或名称找到合适的Bean进行注入。例如: ```java @Service public class MyService { @Autowired private MyDependency myDependency; // ... ...

    基于java的企业级应用开发:Bean的装配方式.ppt

    本节将详细介绍基于XML、注解(Annotation)以及自动装配这三种Bean装配方式。 首先,我们来理解什么是Bean的装配。Bean的装配,也称为依赖注入,是指将对象所需的依赖关系(例如其他对象或服务)设置到该对象中,...

    Spring中的Bean的管理_Bean的装配方式_基于注解的装配_项目

    运行环境eclipse。其Dynamic Web Project,Target Runtime为Apache Tomcat v8.5,Dynamic web module version 为 3.1。 目的:Spring容器已经成功获取了UserController实例,并通过调用实例中的方法执行了各层中的...

    AOP中的注解自动装配通知

    4. **@Configuration和@Bean**:在Spring 3.0引入了@Configuration注解,可以配合@Bean注解创建配置类,以替代XML配置。@Bean注解标记的方法会返回一个Bean实例,Spring容器会将这些实例添加到Bean的定义中。 5. **...

    day38 16-Spring的Bean的装配:注解的方式

    2. **注解Bean定义**:在需要管理的类上添加`@Component`或其派生注解,如`@Service`。 ```java @Service public class UserService { // ... } ``` 3. **依赖注入**:通过`@Autowired`注解来注入依赖。如果依赖...

    IOC之基于注解的配置bean(下)

    - `@Autowired`:这个注解用于自动装配bean的依赖。Spring会根据类型或名称自动查找并注入匹配的bean。 - `@Qualifier`:当有多个相同类型的bean时,可以配合`@Autowired`使用,通过指定bean的名称来精确匹配。 ##...

    JavaEE基础3 、掌握基于注解的装配技术,并编程验证。 2、掌握自动装配技术,并编程验证。

    首先,基于注解的装配技术是Spring框架提供的一种替代XML配置的方式,它允许开发者直接在类或方法上使用注解来声明组件及其属性。这些注解包括@Component(定义一个bean),@Service,@Repository以及@Controller等...

    SpingIOC注入实例化bean

    Spring的@Autowired注解能自动匹配并注入依赖的bean,基于类型或基于名称。当多个候选bean存在时,可以使用@Qualifier注解指定特定的bean。 7. **基于注解的配置** 除了XML配置,Spring还支持基于注解的配置。...

    JavaEE 使用注解配置Bean的一个示例

    4. **@Qualifier**:在存在多个相同类型的Bean时,可以使用@Qualifier注解指定特定的Bean。例如: ```java @Autowired @Qualifier("specificRepository") private UserRepository userRepository; ``` 5. **@Value...

    通过@Autowired注解注入bean的顺序,以及@bean注入.rar

    4. **@Qualifier注解**:如果还有多个bean,且没有`@Primary`,Spring会检查`@Autowired`注解是否带有`@Qualifier`,并根据指定的bean名称进一步筛选。 5. **索引**:如果以上方式都无法确定唯一bean,那么可以为...

    spring bean XML配置入门

    在本文中,我们将深入探讨Spring框架中的Bean XML配置,这是Spring的核心特性之一,它允许我们定义、管理和装配应用中的对象。我们将围绕以下知识点展开: 1. **Spring框架基础**: Spring是一个开源的Java平台,...

    用@Resource注解完成属性装配

    `@Resource`的主要作用是基于名字(byName)进行装配,也就是说,它会寻找匹配的名字来找到相应的bean。 ### `@Resource`注解的基本用法 1. **字段注入**: ```java @Resource private MyService myService; `...

    基于注解的SSH整个框架

    在基于注解的配置中,我们可以使用`@Autowired`注解来自动装配Bean,避免XML配置。此外,Spring MVC作为Spring的一部分,可以用来处理Web请求,通过`@Controller`、`@RequestMapping`等注解定义控制器和映射。 2. *...

    1.spring注解1

    `@Autowired`基于类型匹配,可以自动注入与之类型匹配的Bean,而`@Resource`则基于名称,如果提供`@Param("参数名")`,则会按照指定的名称去寻找Bean。`@Qualifier`可以与`@Autowired`一起使用,用于指定需要注入的...

    Spring与IoC系列四:基于注解的依赖注入.rar

    2. `@Autowired`:此注解用于自动装配Bean的依赖。Spring会根据类型或名称匹配找到合适的依赖并注入。默认是按类型匹配,如果存在多个相同类型的Bean,则可以通过`@Qualifier`指定具体Bean的名称。 3. `@Qualifier`...

    Spring Boot技术知识点:Bean装配1

    6. **配置类与属性源**:Spring Boot允许从application.properties或application.yml文件中读取配置属性,并通过@ConfigurationProperties注解将这些属性映射到Java对象上,方便在Bean装配时使用。 7. **条件注解...

    使用注解自动装配需要组件扫描.zip

    在Spring框架中,注解自动装配(Annotation-based Autowiring)是一种简化依赖注入(Dependency Injection,简称DI)的方式,它允许开发者用注解来声明类的依赖,而无需使用XML配置文件。本教程将深入讲解如何使用...

    spring 装配demo

    在Spring中,装配有两种主要方式:XML配置和基于注解的配置。 描述中提到的"博文链接:https://tomfish88.iteye.com/blog/979781" 提供了一个外部资源,但未提供具体信息。因此,我们无法直接引用该博客内容,不过...

    模拟Spring的IoC容器实现注解自动装配

    4. **装配依赖**:将找到的依赖注入到目标bean中,这可以通过反射来实现。 在模拟实现过程中,我们可能还需要一个`ApplicationContext`接口,它代表了整个应用程序上下文,包含所有bean的集合以及相关的方法,如...

Global site tag (gtag.js) - Google Analytics