Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JavaScript 前端笔记总结(精简)
JavaScript 一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型,属于网络的脚本语言,现在已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果,现在随着node.js引擎的出现,使得JavaScript逐步成为了一种全栈开发语言了.
微软技术分享
2022/12/28
7.6K0
JQuery 实现开发常用功能
标签克隆的两种实现方式: <body> <div> <p> <a onclick="Add(this)">+</a> <input type="text"/> </p> </div> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <script> function Add(ths) {
微软技术分享
2022/12/28
5.4K0
前端基础:jQuery
jQuery 能做的 JavaScript 也都能做,但使用 jQuery 能大幅提高开发效率
RendaZhang
2020/09/08
13.6K0
前端基础:jQuery
Web前端开发JavaScript提高
JS是基于对象的(Object-Based)脚本语言,而不是面向对象(Object-Oriented)中所使用的那个对象,之所以说JS是一门基于对象的编程语言,是因为它没有提供抽象,继承,封装等面向对象语言的很多功能,而是把其他语言所创建的复杂对象统一起来,从而形成一个非常强大的对象系统.
微软技术分享
2022/12/28
2.3K0
E026Web学习笔记-JQuery(四):动画、遍历、事件、插件
訾博ZiBo
2025/01/06
440
E026Web学习笔记-JQuery(四):动画、遍历、事件、插件
前端(四)-jQuery
$(this)就是将这个dom对象转换成jquery对象,就可以对这个对象进行操作;
化羽羽
2022/10/28
8.6K0
Flask 框架基础知识笔记
内置过滤器: tojson配合js使用,注意这里要避免HTML自动转义,所以加上safe过滤器
微软技术分享
2022/12/28
2.4K0
jQuery_T2_DOM操作
当我们点击文字的时候会添加一个【p_text】class,对应的style就会生效。
红目香薰
2022/11/30
7.8K0
jQuery_T2_DOM操作
2022年11月23日——jQuery——T1(基础选择器与表单选择器)
颜色切换,这里是通过$()直接加载js的脚本内容,并且通过jQuery添加了对应下拉菜单的onchange事件,通过这个事件来控制网页的背景颜色。
红目香薰
2022/11/28
5.6K0
2022年11月23日——jQuery——T1(基础选择器与表单选择器)
Web前端学习笔记之jQuery基础
维护IE678是一件让人头疼的事情,一般我们都会额外加载一个CSS和JS单独处理。值得庆幸的是使用这些浏览器的人也逐步减少,PC端用户已经逐步被移动端用户所取代,如果没有特殊要求的话,一般都会选择放弃对678的支持。
Jetpropelledsnake21
2019/02/15
3.6K0
学习jQuery?这篇文章就够了
jQuery 使用户能更方便地处理 HTML(标准通用标记语言下的一个应用)、events、实现动画效果,并且方便地为网站提供 AJAX 交互。 jQuery 的语法设计可以使开发者更加便捷,例如操作文档对象、选择 DOM 元素、制作动画效果、事件处理、使用 AJAX 以及其他功能。
上分如喝水
2021/08/16
12.3K0
04 . 前端之JQuery
JQuery简介 # 1. jQuery是一个轻量级的、兼容多浏览器的JavaScript库。 # 2. jQuery使用户能够更方便地处理HTML Document、Events、实现动画效果、方便
iginkgo18
2020/09/27
3.4K0
Web前端开发初级中级实操
这是某电商类网站服装商品展示页面局部,该网站正在促销秋冬季女装。现在我们需要编写该网站效果图部分代码。
用户7705674
2021/09/19
7.4K0
Django Ajax序列化与反序列化
序列化与反序列是最常用的功能,有时我们需要将一个表单组打包成Json格式等然后再提交给服务端,这样可以提高效率节约带框,如下是Django配合Ajax实现的序列化与反序列化,文件上传等操作。
微软技术分享
2022/12/28
2.8K0
JavaScript 前端知识点总结
Java Script 是基于对象的脚本语言,而不是面向对象中所使用的那个对象,之所以说JS是一门基于对象的编程语言,是因为它没有提供抽象,继承,封装等面向对象语言的很多功能,而是把其他语言所创建的复杂对象统一起来,从而形成一个非常强大的对象系统.
微软技术分享
2022/12/28
2.5K0
与Ajax同样重要的jQuery(1)
jQuery框架 jQuery 1.4 是企业主流版本,从jQuery1.6 开始引入大量新特性。最新版本 2.1.1,这里讲解以1.8.3为主(新版本主要是浏览器兼容问题以及新特性) jQuery 提供 jquery-1.8.3.js 和 jquery-1.8.3.min.js jquery-1.8.3.js jQuery框架源码,没有被精简,体积较大 (主要用来研究 jQuery源码),企业开发时,需要导入 jquery-1.8.3.min.js (精简过) 1.jQuery程序快速入门 window.
Java帮帮
2018/03/19
10K0
与Ajax同样重要的jQuery(1)
jQuery
ps:.offset()方法允许我们检索一个元素相对于文档(document)的当前位置,和 .position()的差别在于: .position()是相对于相对于父级元素的位移;
HammerZe
2022/03/25
6.8K0
jQuery
Web前端知识系列(包括web前端全部知识点)
HTML:Hyper Text Markup Language :超文本标记语言。
软件小生活
2021/09/06
2.2K0
Web前端知识系列(包括web前端全部知识点)
Web阶段:第五章:JQuery库
点击:API文档下载 Jquery介绍 1.什么是JQuery ? jQuery,顾名思义,也就是JavaScript和查询(Query),它就是辅助JavaScript开发的js类库。 2.JQue
Java廖志伟
2022/09/28
26.3K0
Web阶段:第五章:JQuery库
与Ajax同样重要的jQuery(2)
练习9: ² 点击button 打印radio checkbox select 中选中项的值 <script type="text/javascript" src="../jquery-1.8.3.min.js"></script> <script type="text/javascript"> $(function(){ // 点击button 打印radio checkbox select 中选中项的值 $("#mybutton").click(function(){ // 打印选中性别的值 $("in
Java帮帮
2018/03/19
6.2K0
与Ajax同样重要的jQuery(2)
相关推荐
JavaScript 前端笔记总结(精简)
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文