Autowired使用说明

本文详细介绍了Spring框架中Autowired注解的工作原理及其使用条件。通过示例代码解释了如何使Autowired生效,并探讨了其在不同场景下的应用。

使用了那么久Spring,一下子问我Autowired注解使用条件,答不上来吧,看了Spring源码,一点点收货;

 废话少说,要是Autowired生效,需要注册BeanPostProcessor,你说我没注册也能用啊,那你一定用了<context:annotation-config>或者<context:component-scan base-package="扫描包名/>这两个注解吧;

 

简单的测试代码(两个类 Person  以及 Pet  ,一个Person类持有一个Pet类的关系)

  Person类:

package com.lvbinbin.autowired;
import org.springframework.beans.factory.annotation.Autowired;
public class Person {
    private String name;
    
    @Autowired
    private Pet pet;

    public String toString() {
        return "Person name:" + name + ",Pet:" + pet;
    }

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

    Pet类:

package com.lvbinbin.autowired;
public class Pet {
    private String name;

    public String toString() {
        return "Pet name:"+name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

  Spring的配置文件(将Person以及Pet放到Spring容器里,或者通过包扫描加入容器)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 6         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 7 
 8 <bean id="person1" class="com.lvbinbin.autowired.Person">
 9     <property name="name" value="lvbinbin"></property>
10 </bean>
11 
12 <bean id="pet1" class="com.lvbinbin.autowired.Pet">
13     <property name="name" value="xiaobinggan"/>
14 </bean>
15 </beans>

简单写个类测试一下:

 1 package com.lvbinbin.autowired;
 2 
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 
 5 public class TestCases {
 6 
 7     public static void main(String[] args) {
 8         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/lvbinbin/autowired/spring.xml");
 9         Person p1=(Person) context.getBean("person1");
10         System.out.println(p1);
11     }
12 }

   以上代码,测试发现没有注入Pet属性; 也说明了 XML文件 property注入属性需要有对应的Setter  Getter方法;

 

  在Spring配置文件中加入下面几句话之一,Autowired就可以生效:   <bean id="aabp" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

                            或者 <context:annotation-config/> 

                            或者 <context:component-scan base-package="包路径"/>  

其中包路径随意写也能使用Autowired注解生效,但是不建议写无意义的路径;

 额外注意几点:  1. Autowired注解只有一个属性  required  可选值 false / true :  默认为true ,如果实例化该属性时候,IOC容器即BeanFactory中没有可以注入的,抛出异常 ;

                                   设置为false ,实例化该属性时候 容器里没有该类型的bean 同样可以运行 ;

                          2.Autowired注解的属性可以有setter  getter方法;底层是通过反射设置上的值,setter getter方法需不需要都可以成功 ;

                          3.Autowired注解可以标注在属性、或者方法上, 但是属性和方法都不允许为 static 类型;

        4.Autowired注解可以注入一些Spring默认配置上的,ApplicationContext、BeanFactory、Enviroment等等对象;

        5.Autowired注解标注在方法上时,方法入参需要都在SpringIOC容器中存在,该类型对象有一个不存在就会抛出异常

偷懒给Person类添加一些public属性;

测试main方法如下:

 1 public static void main(String[] args) {
 2         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/lvbinbin/autowired/spring.xml");
 3         Person p1=(Person) context.getBean("person1");
 4         System.out.println(p1);
 5         System.out.println("ac:"+p1.ac);
 6         System.out.println("bf:"+p1.bf);
 7         System.out.println("rl:"+p1.rl);
 8         System.out.println("ap:"+p1.ap);
 9         System.out.println("env:"+p1.env);
10     }

查看下输出:其实ResourceLoader、ApplicationEventPublisher都是ApplicationContext的具体对象,因为ApplicationContext实现了这些接口;

 

 

博客的最后,记录一个笨比的尝试:(下面的例子是Spring源码编译后改动,编译教程建议看Spring源码深度解析)

Autowired注解可以标注在 方法入参上,测试一下:

上例Person类简单改造下:注释掉 Pet属性上的Autowired,在方法入参中加上@Autowired;这里补充下:Autowired的注解的方法名不一定非要set这种形式的方法;

1     // @Autowired
2     private Pet pet;
3     
4     public void test1(@Autowired Pet p) {
5         this.pet=p;
6     }

同样的测试用例:发现Pet属性并没有注入上去(如果可以注入上去望指教);

 简单改造下,可以支持 单个参数的Autowired注入,多个参数的Autowired实现,我力有不逮;

AutowiredAnnotationBeanPostProcessor的 findAutowiredAnnotation方法简单改造下,如果入参是Method且没有注解标注,顺便检查下参数上是否有Autowired注解,没有再返回null,就可以简单实现单个参数上的Autowired功能吧

 1       @Nullable
 2     private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
 3         if (ao.getAnnotations().length > 0) {  // autowiring annotations have to be local
 4             for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
 5                 AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
 6                 if (attributes != null) {
 7                     return attributes;
 8                 }
 9             }
10         }
        return null;
11 }

改造添加几行代码后方法这样的:

 1 @Nullable
 2     private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
 3         if (ao.getAnnotations().length > 0) {  // autowiring annotations have to be local
 4             for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
 5                 AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
 6                 if (attributes != null) {
 7                     return attributes;
 8                 }
 9             }
10         }
11         if(ao instanceof Method) {
12             Parameter[] parameters = ((Method) ao).getParameters();
13             for (Parameter parameter : parameters) {
14                 for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
15                     AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(parameter, type);
16                     if (attributes != null) {
17                         return attributes;
18                     }
19                 }
20             }      
21         }
22         return null;
23     }

同样的我们再测试下:发现已经可以实现了Autowired单个属性的注入,多个属性的改造量太大,可以(wo)但(bu)没必要(hui);

 

            

 

转载于:https://www.cnblogs.com/lvbinbin2yujie/p/10073314.html

<think>好的,我现在需要帮助用户了解Spring框架中@Autowired注解的使用条件和场景。首先,我得回忆一下相关的知识,并结合提供的引用内容来组织回答。 用户的问题是关于@Autowired使用条件和场景,所以我需要明确几点:什么时候必须使用@Autowired,什么时候可以省略,以及在不同情况下如何正确应用。根据引用中的信息,比如引用[1]提到从Spring 4.3开始,如果目标bean只有一个构造器,可以不加@Autowired;如果有多个构造器,则需要显式注解。另外,方法注入如setter方法也需要使用@Autowired。引用[3]提到@Autowired是基于类型的自动装配,默认按类型匹配,如果有多个同类型bean需要其他方式指定。 接下来需要整理这些信息,分点回答使用条件和适用场景。使用条件可能包括构造器注入的条件、setter或字段注入的必要性,以及处理多个候选bean的情况。适用场景可能包括构造器注入推荐用于强依赖,setter用于可选依赖,字段注入的便捷性等。 还要注意是否需要提到@Qualifier或@Primary来处理多个同类型bean的情况,这在引用[3]中提到过。另外,引用[4]可能提到不适用的场景,比如静态字段、非Spring管理的类等,但用户的问题主要是条件和场景,可能不需要深入这些例外,但可能需要简要提及。 需要确保回答结构清晰,分点列出,并且每个点都结合引用内容,例如引用[1]和[3]的具体说明。同时,按照用户的要求,生成相关问题,比如关于多个构造器、处理多个bean的方法,或者不同注入方式的区别。 最后,检查是否符合系统级指令,如使用正确的中文,数学表达式格式(虽然这个问题可能不需要数学公式),以及正确引用标记。确保回答中没有使用任何Markdown格式,段落之间用空行分隔,代码块正确使用反引号,引用标识正确放置。</think>### Spring @Autowired 注解的使用条件及场景 #### 一、@Autowired使用条件 1. **构造器注入** - 当类**仅有一个构造器**时,从Spring 4.3开始,无需显式添加`@Autowired`,Spring会自动注入依赖[^1]。 - 如果类有**多个构造器**,必须通过`@Autowired`明确指定需要使用的构造器。 ```java // 多个构造器时需明确标注 @Autowired public MyService(Repository repo) { /* ... */ } ``` 2. **Setter方法或字段注入** - 在Setter方法或字段上添加`@Autowired`,Spring会通过反射注入依赖。例如: ```java @Autowired public void setDependency(Dependency dep) { /* ... */ } @Autowired private Dependency dependency; ``` 3. **依赖的Bean必须存在且唯一** - 默认按类型(`byType`)匹配。若容器中存在**多个同类型的Bean**,需结合`@Qualifier`或`@Primary`明确指定具体Bean[^3]。 --- #### 二、适用场景 1. **构造器注入(推荐)** - **强依赖场景**:如数据库连接、核心服务类。构造器注入确保对象创建时依赖已就绪,避免空指针异常[^3]。 2. **Setter方法注入** - **可选依赖或需动态变更的依赖**:例如配置参数或可替换的实现类。 ```java @Autowired public void setCacheProvider(CacheProvider provider) { /* ... */ } ``` 3. **字段注入** - **简化代码的快速开发**:适用于非公共字段或测试类,但需注意对容器强依赖的问题。 4. **方法注入** - **初始化后执行逻辑**:例如在某个方法中注入工具类并初始化数据。 ```java @Autowired public void init(Config config) { /* ... */ } ``` --- #### 三、不适用或需谨慎的场景 1. **静态字段或方法** - `@Autowired`无法直接注入静态成员,需通过`@PostConstruct`间接实现[^4]。 2. **非Spring管理的类** - 普通POJO类(未标注`@Component`等注解)无法通过`@Autowired`注入依赖。 3. **循环依赖** - 若两个Bean互相依赖,可能引发循环依赖问题,需通过懒加载(`@Lazy`)或Setter方法解决。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值