注解@autowired与@resources的区别

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它是J2EE的,它的包是javax.annotation.Resource,而@Autowired的包是org.springframework.beans.factory.annotation.Autowired,但Spring支持该注解的注入(Spring支持几个JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct、@PreDestroy)。

/***************  @Autowired源码  ***************/
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    /**
     * Declares whether the annotated dependency is required.
     * 

Defaults to {@code true}. */ boolean required() default true; }

/***************  @Resource源码  ***************/
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {

    //两个重要属性:name和type
    String name() default "";
    String lookup() default "";
    Class type() default java.lang.Object.class;

    /**
     * The two possible authentication types for a resource.
     */
    enum AuthenticationType {
            CONTAINER,
            APPLICATION
    }
    AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
    boolean shareable() default true;
    String mappedName() default "";
    String description() default "";
}
  1. 共同点
    两者都可以写在字段和setter方法上。两者如果都写在字段上,那么不需要再写setter方法。
public class TestServiceImpl {
    // 下面两种@Autowired只要使用一种即可
    @Autowired
    private UserDao userDao; // 用于字段上

    @Autowired
    public void setUserDao(UserDao userDao) { // 用于属性的方法上
        this.userDao = userDao;
    }
}

2.不同点
(1)@Autowired只按照byType注入。默认情况下要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false。如:@Autowired(required=false),如果我们想使用byName注入,可以结合@Qualifier注解进行使用,如下:

@Autowired(required=false)
@Qualifier("userDao")
private UserDao userDao;

(2)@Resource默认按照byName自动注入,有两个重要属性:name和type。Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用那么属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略,如果既不指定name也不指定type属性,这是将通过反射机制使用byName自动注入。

public class TestServiceImpl {
    // 下面两种@Resource只要使用一种即可
    @Resource(name="userDao")
    private UserDao userDao; // 用于字段上

    @Resource(name="userDao",type=UserDao.class)
    public void setUserDao(UserDao userDao) { // 用于属性的setter方法上
        this.userDao = userDao;
    }
}

@Resource装配顺序:

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
  3. 如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或找到多个,都会抛出异常。
  4. 如果既没有指定name,也没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个byType进行匹配,如果匹配则自动装配。通过设置CommonAnnotationBeanPostProcessor 的‘fallbackToDefaultTypeMatch’属性为“false”(默认值是“true”)可以禁用这一特性。



  5. 在解析@Resource注解的依赖时,Spring支持JNDI-lookup(JAVA Naming and Directory Interface,Java命名和目录接口)。如若要强制对所有使用@Resource注解的依赖进行JNDI-lookup,那也只要将CommonAnnotationBeanPostProcessor的‘alwaysUseJndiLookup’标识设置为true就可以了(默认值是false)。


  6. 另一个选择是,激活指定为‘resource-ref-mappings’的依据全局JNDI名的查找,在@Resource注解内提供‘mappedName’属性。即使目标对象实际上是一个JNDI资源,仍然推荐引入一个Spring管理对象,这样可以提供一个间接层并且因此降低耦合程度。自Spring2.0开始添加命名空间以来,定义一个委托Spring处理JNDI lookup的bean也变得愈发简练:
id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/>

这个方法的优点在于间接层带来了巨大的部署弹性。比如说,一个单独的系统测试环境应该不再需要JNDI注册。在这种情况下,在系统测试配置中可以提供如下的bean定义:

"dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />

顺便提一下,上面的例子中,实际的JDBC连接属性从一个属性文件(properties file)解析而来,在这个属性文件里,关键字与提供的${占位符}互相对应,这需要注册一个名为PropertyPlaceholderConfigurer的BeanFactoryPostProcessor实现来完成。这是具体化那些属性(通常是针对特定环境的属性)常用的技术,这些属性可能比其他配置修改得更为频繁。

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
bean>

Srping2.5中新加入了‘context’命名空间,这个命名空间让我们能够得到更为简洁的方式来实现属性占位符(property placeholder)的配置:

<context:property-placeholder location="classpath:jdbc.properties"/>

@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入

你可能感兴趣的:(spring,java)