前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Spring注解-@Autowired注解使用

Spring注解-@Autowired注解使用

作者头像
SerMs
发布于 2022-04-11 07:09:58
发布于 2022-04-11 07:09:58
1K00
代码可运行
举报
文章被收录于专栏:SerMsBlogSerMsBlog
运行总次数:0
代码可运行

写在前面得话

学习@Autowired之前建议先学会使用byType和byName

Spring的自动装配

https://hgm.vercel.app/post/63755f3a/

@Autowired详解

首先要知道另一个东西,default-autowire,它是在xml文件中进行配置的,可以设置为byName、byType、constructor和autodetect;比如byName,不用显式的在bean中写出依赖的对象,它会自动的匹配其它bean中id名与本bean的set**相同的,并自动装载。 @Autowired是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源。 两者的功能是一样的,就是能减少或者消除属性或构造器参数的设置,只是配置地方不一样而已。 autowire四种模式的区别

先看一下bean实例化和@Autowired装配过程: 一切都是从bean工厂的getBean方法开始的,一旦该方法调用总会返回一个bean实例,无论当前是否存在,不存在就实例化一个并装配,否则直接返回。(Spring MVC是在什么时候开始执行bean的实例化过程的呢?其实就在组件扫描完成之后)

实例化和装配过程中会多次递归调用getBean方法来解决类之间的依赖。

Spring几乎考虑了所有可能性,所以方法特别复杂但完整有条理。

@Autowired最终是根据类型来查找和装配元素的,但是我们设置了后会影响最终的类型匹配查找。因为在前面有根据BeanDefinition的autowire类型设置PropertyValue值得一步,其中会有新实例的创建和注册。就是那个autowireByName方法。

下面通过@Autowired来说明一下用法

Setter 方法中的 @Autowired

你可以在 JavaBean中的 setter 方法中使用 @Autowired 注解。当 Spring遇到一个在 setter 方法中使用的 @Autowired 注解,它会在方法中执行 byType 自动装配。 这里是 TextEditor.java 文件的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
    private SpellChecker spellChecker;
    @Autowired
    public void setSpellChecker( SpellChecker spellChecker ){
        this.spellChecker = spellChecker;
    }
    public SpellChecker getSpellChecker( ) {
        return spellChecker;
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

下面是另一个依赖的类文件 SpellChecker.java 的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.tutorialspoint;
public class SpellChecker {
    public SpellChecker(){
        System.out.println("Inside SpellChecker constructor." );
    }
    public void checkSpelling(){
        System.out.println("Inside checkSpelling." );
    }  
}

下面是 MainApp.java 文件的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        TextEditor te = (TextEditor) context.getBean("textEditor");
        te.spellCheck();
    }
}

下面是配置文件 Beans.xml:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>

    <!-- Definition for textEditor bean without constructor-arg  -->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
    </bean>

    <!-- Definition for spellChecker bean -->
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
    </bean>

</beans>

一旦你已经完成的创建了源文件和 bean 配置文件,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside SpellChecker constructor. Inside checkSpelling.

属性中的 @Autowired

你可以在属性中使用 @Autowired 注解来除去 setter 方法。当时使用 为自动连接属性传递的时候,Spring 会将这些传递过来的值或者引用自动分配给那些属性。所以利用在属性中 @Autowired 的用法,你的 TextEditor.java 文件将变成如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
    @Autowired
    private SpellChecker spellChecker;
    public TextEditor() {
        System.out.println("Inside TextEditor constructor." );
    }  
    public SpellChecker getSpellChecker( ){
        return spellChecker;
    }  
    public void spellCheck(){
        spellChecker.checkSpelling();
    }
}

下面是配置文件 Beans.xml:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>

    <!-- Definition for textEditor bean -->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
    </bean>

    <!-- Definition for spellChecker bean -->
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
    </bean>

</beans>

一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside TextEditor constructor. Inside SpellChecker constructor. Inside checkSpelling.

构造函数中的 @Autowired

你也可以在构造函数中使用 @Autowired。一个构造函数 @Autowired 说明当创建 bean 时,即使在 XML 文件中没有使用 元素配置 bean ,构造函数也会被自动连接。让我们检查一下下面的示例。 这里是 TextEditor.java 文件的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
    private SpellChecker spellChecker;
    @Autowired
    public TextEditor(SpellChecker spellChecker){
        System.out.println("Inside TextEditor constructor." );
        this.spellChecker = spellChecker;
    }
    public void spellCheck(){
        spellChecker.checkSpelling();
    }
}

下面是配置文件 Beans.xml:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>

    <!-- Definition for textEditor bean without constructor-arg  -->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
    </bean>

    <!-- Definition for spellChecker bean -->
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
    </bean>

</beans>

一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:

Inside TextEditor constructor. Inside SpellChecker constructor. Inside checkSpelling.

@Autowired 的(required=false)选项

默认情况下,@Autowired 注解意味着依赖是必须的,它类似于 @Required 注解,然而,你可以使用 @Autowired 的 (required=false) 选项关闭默认行为。 即使你不为 age 属性传递任何参数,下面的示例也会成功运行,但是对于 name 属性则需要一个参数。你可以自己尝试一下这个示例,因为除了只有 Student.java 文件被修改以外,它和 @Required 注解示例是相似的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
    private Integer age;
    private String name;
    @Autowired(required=false)
    public void setAge(Integer age) {
        this.age = age;
    }  
    public Integer getAge() {
        return age;
    }
    @Autowired
    public void setName(String name) {
        this.name = name;
    }   
    public String getName() {
        return name;
    }
}

其他

@Autowired注释应用于具有任意名称和多个参数的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
                        CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

您也可以将@Autowired应用于字段,或者将其与构造函数混合,如以下示例所示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    private MovieCatalog movieCatalog;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

将@Autowired注释添加到需要该类型数组的字段或方法,则spring会从ApplicationContext中搜寻符合指定类型的所有bean,如以下示例所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MovieRecommender {

    @Autowired
    private MovieCatalog[] movieCatalogs;

    // ...
}

数组可以,我们可以马上举一反三,那容器也可以吗,答案是肯定的,下面是set以及map的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MovieRecommender {

    private Set<MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }

    // ...
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MovieRecommender {
 
    private Map<String, MovieCatalog> movieCatalogs;
 
    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
 
    // ...
}

以上就是@Autowired注解的主要使用方式,经常使用spring的话应该对其中常用的几种不会感到陌生。

@Autowired装配不成功的几种情况?

没有加@Component注解

在类上面忘了加@Controller、@Service、@Component、@Repository等注解,spring就无法完成自动装配的功能,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class UserService {
    @Autowired    
    private IUser user;    
    public void test() {        
        user.say();    
    }
}

这种情况应该是最常见的错误了,不会因为你长得帅,就不会犯这种低级的错误。

注入Filter或Listener

web应用启动的顺序是:listener->filter->servlet。

接下来看看这个案例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class UserFilter implements Filter {
    @Autowired
    private IUser user;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        user.say();
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    }
    @Override
    public void destroy() {
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class FilterConfig {
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        bean = new FilterRegistrationBean();
        bean.setFilter(new UserFilter());
        bean.addUrlPatterns("/*");
        return bean;
    }
}

程序启动会报错,tomcat也无法正常启动???什么原因??

众所周知,springmvc的启动是在DisptachServlet里面做的,而它是在listener和filter之后执行。如果我们想在listener和filter里面@Autowired某个bean,肯定是不行的,因为filter初始化的时候,此时bean还没有初始化,无法自动装配。

如果工作当中真的需要这样做,我们该如何解决这个问题呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class UserFilter  implements Filter {
    private IUser user;    

    @Override    
    public void init(FilterConfig filterConfig) throws ServletException {        
        ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(
            filterConfig.getServletContext());        
        this.user = ((IUser)(applicationContext.getBean("user1")));        
        user.say();    
    }    

    @Override    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  

    }   

    @Override    
    public void destroy() {  

    }
}

答案是使用 WebApplicationContextUtils.getWebApplicationContext获取当前的ApplicationContext,再通过它获取到bean实例。

注解未被@ComponentScan扫描

通常情况下,@Controller、@Service、@Component、@Repository、@Configuration等注解,是需要通过@ComponentScan注解扫描,收集元数据的。

但是,如果没有加@ComponentScan注解,或者@ComponentScan注解扫描的路径不对,或者路径范围太小,会导致有些注解无法收集,到后面无法使用@Autowired完成自动装配的功能。

有个好消息是,在springboot项目中,如果使用了@SpringBootApplication注解,它里面内置了@ComponentScan注解的功能。

循环依赖问题

如果A依赖于B,B依赖于C,C又依赖于A,这样就形成了一个死循环。

spring的bean默认是单例的,如果单例bean使用@Autowired自动装配,大多数情况,能解决循环依赖问题。

但是如果bean是多例的,会出现循环依赖问题,导致bean自动装配不了。

还有有些情况下,如果创建了代理对象,即使bean是单例的,依然会出现循环依赖问题。

@Autowired和@Resouce的区别

@Autowired功能虽说非常强大,但是也有些不足之处。比如:比如它跟spring强耦合了,如果换成了JFinal等其他框架,功能就会失效。而@Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持。

除此之外,有些场景使用@Autowired无法满足的要求,改成@Resource却能解决问题。接下来,我们重点看看@Autowired和@Resource的区别。

  • @Autowired默认按byType自动装配,而@Resource默认byName自动装配。
  • @Autowired只包含一个参数:required,表示是否开启自动准入,默认是true。而@Resource包含七个参数,其中最重要的两个参数是:name 和 type。
  • @Autowired如果要使用byName,需要使用@Qualifier一起配合。而@Resource如果指定了name,则用byName自动装配,如果指定了type,则用byType自动装配。
  • @Autowired能够用在:构造器、方法、参数、成员变量和注解上,而@Resource能用在:类、成员变量和方法上。
  • @Autowired是spring定义的注解,而@Resource是JSR-250定义的注解。

此外,它们的装配顺序不同。

@Autowired的装配顺序如下:

@Resource的装配顺序如下:

1.如果同时指定了name和type:

如果指定了name:

如果指定了type:

如果既没有指定name,也没有指定type:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring - 注入内部 Bean
如您所知,Java 内部类是在其他类的范围内定义的,类似地,内部 bean是在另一个 bean 的范围内定义的 bean。因此,<property/> 或 <constructor-arg/> 元素内的 <bean/> 元素称为内部 bean,如下所示。
IT胶囊
2021/08/30
8700
Spring 5.0中文版-3.9
3.9 基于注解的容器配置 在配置Spring时注解是否比XML更好? 基于注解配置的引入引出了一个问题——这种方式是否比基于XML的配置更好。简短的回答是视情况而定。长一点的回答是每种方法都有它的优点和缺点,通常是由开发者决定哪一种策略更适合他们。由于注解的定义方式,注解在它们的声明中提供了许多上下文,导致配置更简短更简洁。然而,XML擅长连接组件而不必接触源代码或重新编译它们。一些开发者更喜欢接近源代码,而另一些人则认为基于注解的类不再是POJOs,此外,配置变的去中心化,而且更难控制。 无论选择
JavaEdge
2018/05/16
1.7K0
Spring框架参考手册_5.0.0_中英文对照版_Part II_3.9
An alternative to XML setups is provided by annotation-based configuration which rely on the bytecode metadata for wiring up components instead of angle-bracket declarations. Instead of using XML to describe a bean wiring, the developer moves the configuration into the component class itself by using annotations on the relevant class, method, or field declaration. As mentioned in the section called “Example: The RequiredAnnotationBeanPostProcessor”, using a BeanPostProcessor in conjunction with annotations is a common means of extending the Spring IoC container. For example, Spring 2.0 introduced the possibility of enforcing required properties with the @Required annotation. Spring 2.5 made it possible to follow that same general approach to drive Spring’s dependency injection. Essentially, the @Autowired annotation provides the same capabilities as described in Section 3.4.5, “Autowiring collaborators” but with more fine-grained control and wider applicability. Spring 2.5 also added support for JSR-250 annotations such as @PostConstruct, and @PreDestroy. Spring 3.0 added support for JSR-330 (Dependency Injection for Java) annotations contained in the javax.inject package such as @Inject and @Named. Details about those annotations can be found in the relevant section.
Tyan
2019/05/25
1.2K0
面试官:Spring中的注解@Autowired是如何实现的
现在面试,基本上都是面试造火箭????,工作拧螺丝????。而且是喜欢问一些 Spring 相关的知识点,比如 @Autowired 和 @Resource 之间的区别。魔高一丈,道高一尺。很快不少程
业余草
2021/12/06
3870
面试官:Spring中的注解@Autowired是如何实现的
经典面试题-请举例解释@Autowired注解?
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
cwl_java
2019/11/07
8700
@Autowired背后实现的原理,你都知道吗
使用spring开发时,进行配置主要有两种方式,一是xml的方式,二是java config的方式。
公众号 IT老哥
2021/11/04
2.1K0
经典Spring面试十题(二)
原文:https://blog.csdn.net/u012562943/article/details/51397417
用户5224393
2019/08/13
3500
Spring 必知概念(二)
13、Spring框架中的单例Beans是线程安全的么? Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Sp
冷冷
2018/02/08
7590
Spring:轻松驾驭 Java 世界的利器
在 Java 开发领域,Spring 框架无疑是一颗璀璨的明星,它不仅提供了全面的企业级特性,还为开发者提供了简便而强大的开发方式。本文将深入探讨 Spring 框架的简介、配置和快速入门,带你轻松驾驭 Java 世界的利器。
繁依Fanyi
2024/01/03
1470
I-o-C 一篇概览
IoC(Inversion of Control )也被称之为 DI(dependency injection),名称侧重点略有不同。
WindWant
2023/05/09
1.1K0
I-o-C 一篇概览
Spring Bean 的装配方式以及Autowired与Resource的使用及区别
在Spring的使用中,如果要将一个bean实例化,可以通过配置文件,也可以通过在java代码里面的注解来实现,Spring能够根据自动协作这些bean之间的关系,这种自动协作的过程,也称之为自动装配。 自动装配模式有如下四种模式:
冬天里的懒猫
2021/09/08
7290
Spring 学习笔记(五)—— Bean之间的关系、作用域、自动装配
  Spring提供了配置信息的继承机制,可以通过为<bean>元素指定parent值重用已有的<bean>元素的配置信息。
Rekent
2018/09/04
4860
Spring 学习笔记(五)—— Bean之间的关系、作用域、自动装配
Spring面试问答
Spring框架是一个为Java应用程序的开发提供了综合、广泛的基础性支持的Java平台。Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发。Spring框架本身亦是按照设计模式精心打造,这使得我们可以在开发环境中安心的集成Spring框架,不必担心Spring是如何在后台进行工作的。
哲洛不闹
2018/09/19
5680
Spring面试问答
Java后端的学习之Spring基础
Java后端的学习之Spring基础 如果要学习spring,那么什么是框架,spring又是什么呢?学习spring中的ioc和bean,以及aop,IOC,Bean,AOP,(配置,注解,api)
达达前端
2022/04/29
3760
Java后端的学习之Spring基础
25个经典的Spring面试问答
本人收集了一些在大家在面试时被经常问及的关于Spring的主要问题,这些问题有可能在你下次面试时就会被问到。对于本文中未提及的Spring其他模块,我会单独分享面试的问题和答案。
bear_fish
2018/09/19
7580
25个经典的Spring面试问答
@Qualifier注解
如果在xml中定义了一种类型的多个bean,同时在java注解中又想把其中一个bean对象作为属性,那么此时可以使用@Qualifier加@Autowired来达到这一目的,若不加@Qualifier这个注解,在运行时会出现“ No qualifying bean of type [com.tutorialspoint.Student] is defined: expected single matching bean but found 2: student1,student2”这个异常
johnhuster的分享
2022/03/28
5090
JAVAEE框架之Spring注解
通过注解来实现依赖注入,为什么要学这个呢???之前的bean的配置都在哪里呢?都放在了beans.xml这个文件里面。当项目有很多个bean需要配置的时候,假设有30张表,需要配置每个表对应的dao实现类、service实现类,会导致配置文件比较臃肿。今天通过使用注解来简化bean文件的配置。
用户9184480
2024/12/13
620
相关推荐
Spring - 注入内部 Bean
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验