@Autowired注解和启动自动扫描的三种方式(spring bean配置自动扫描功能的三种方式)
前言:
@Autowired注解代码定义
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD,
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
从上述定义中,我们可以得出@Autowired注解只有一个属性即required属性,此属性的默认值为true,即默认情况下它要求依赖对象必须存在,如果不存在会出现空指针等错误;如果允许为null,可以设置它required属性为false.其中@Autowired注解和标注的变量的类的set和get方法无关,自动装配的实现并不是依赖set方法的方式实现的.在xml中利用
<property name="" value="" />
这种方式是依赖对应类的set方法的方式实现的 @Autowired注解使用之前首先确定判断一下此处能够使用@Autowired注解.
一、 @Autowired注解使用场景介绍
(1)构造函数
(2)成员变量
(3)Setter方法
(4)普通方法
二、 @Autowired注解所涉及的原理部分
其实在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
注意事项:
在使用@Autowired时,首先在容器中查询对应类型的bean,
如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
如果查询的结果不止一个,那么@Autowired会根据名称来查找。
如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false
上述过程说明了@Autowired注解默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在如果允许为null,可以设置它required属性为false,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
三、 处理使用@Autowired注解出现自动装配的歧义性问题
使用@Autowired注解的过程中,如果出现NoUniqueBeanDefinitionException异常,大多是因为自动装配或者其他方式装配所导致的歧义性.即一个接口存在两个以上的实现类.即在自动装配的时候,可能出现因重名问题导致的NoUniqueBeanDefinitionException异常.
@Autowired是按类型进行装配的,那么我一个接口UserInterface,有多个实现类
AImpl(@service(name="userInterface1")),BImpl(@service(name="userInterface2")
等等这些实现类都加入了Spring容器,当在一个类中使用如下语句:
@Autowired
private IUserInterface userInterface;
在下面列举一下了一下,上述问题以及类似的装配歧义性解决问题方法.
方法一
首先加上注解@Qualifier来区分不同的实例.通过在实现接口的类上通过value属性去命名不同的名称,对于@Repository、@Service 和 @Controller 和 @Component四个注解都有类似value属性可以设置,例如:
@Service(value="userServiceImpl")
public class UserServiceImpl implements IUserService{ } @Autowired
@Qualifier("userServiceImpl")
private IUserService userServiceImpl;
方法二
因为一个接口存在两个以上的实现类,也可以通过标识首选哪个bean,来解决歧义性问题.例如:
@Component
@Primary
public class UserServiceImpl implements IUserService{ }
此时,如果引用到了IUserService接口的实现类注入,则首先注入@Promary注解标注的类,但是此时有一个问题,在同一个接口的实现类中,你只能使用一次@Primary,如果对于AImpl和BImpl都使用了@primary,则还是会发生装配的歧义性.此时,建议使用(1)的方式来解决歧义性问题.
方法三
最后一种方式,可以使用自定义的限定符注解,但是此种情况很少出现,再次就不做介绍,可自行百度.
四、 Spring通过哪些特性实现自动装配的?
Spring从两个角度来实现自动化装配:
(1)组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean.
(2)自动装配(autowiring):Spring自动满足bean之间的依赖.
组件扫描和自动装配组合在一起就能发挥出强大的威力,它们能够将你的显示配置降低到最少.
五、@Autowired和@Resource之间的区别
在本文只列举出@Autowired和@Resource之间常见的表面区别,至于区别的原因需要查看Spring官方文档中的@Autowired注解实现方式和Java中@Resource注解实现方式.
(1)、@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在如果允许为null,可以设置它required属性为false,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
(2)、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
(3)、@Resource注解是由J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用@Resource的方式;
(4)、@Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上
(5)、@Resource默认按照名称装配,当找不到与名称匹配的bean才会按照类型装配,可以通过name属性指定,如果没有指定name属 性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找 依赖对象.注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖的对象时候,会回退到按照类型装配,但一旦指定了name属性,就只能按照名称装配了.
六、Spring是如何启动自动扫描的
在这里列举出三种启动自动扫描的方式.
方式一:此种情况下,针对比较特殊的情形,即项目中运用了SpringBoot,则可以利用@SpringBootApplication注解的方式启动自动扫描功能.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class Application { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
方式二:通过XML配置方式,启动自动扫描功能.XML配置方式
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.tianmaying" />
</beans>
标签将会开启Spring Beans的自动扫描,并可设置base-package属性,表示Spring将会扫描该目录以及子目录下所有被@Component标注修饰的类,对它们进行装配。
方式三:通过Java配置方式,启动自动扫描功能.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.cn.config")
public class BlogSystemConfig {
/**
* 在这里实现java方式的配置,
*/
}
在这里给出一个具体的实例:
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan(basePackages = "com.cn.config")
public class DataSourceConfig { @Bean(name="dataSource")//java配置方式,配置数据源(dataSource)
public BasicDataSource dataSource(){
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/center_db?useUnicode=true&characterEncoding=UTF-8");
dataSource.setUsername("postgres");
dataSource.setPassword("123456");
dataSource.setInitialSize(5);
dataSource.setMaxActive(10);
return dataSource;
} }
关于@Configuration和@ComponentScan两个注解:
(1)@Configuration表示这个Java文件是一个配置文件,这类Java代码的作用在于配置,要和普通的Java代码区分开发,因此一般我们需要将其放在一个专门的包中,在代码例子中是com.cn.config。
(2)@ComponentScan表示开启Spring Beans扫描,类似于XML配置,这里也可以可以设置basePackages属性。
如果@ComponentScan注解没有显示去给其他的属性赋值的话,比如此处给basePackages赋值了,如果没有的话,@ComponentScan注解会扫描与配置类相同的包.
注意:
关于@Repository、@Service 和 @Controller 和 @Component四个注解的使用情形
在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释.这里就是说把这个类交给Spring管理,重新起个名字叫userManager,由于不好说这个类属于哪个层面,就用@Component.
七、Spring存在几种装配方式?
目前,在Spring中,一共提供三种装配方式:
(1)基于标注的自动装配
(2)基于XML配置的显式装配
(3)基于Java配置的显式装配
在实际项目中,一般是上述三种装备方式都可能存在,不过基于标注的自动装配方式是在项目中最常用的.通过给Java类增加相应的标注,就能够启用Spring隐式的Bean发现机制,并自动完成装配过程.我们在开发中应该尽可能使用自动装配,足以应付开发中的绝大多数情况.在某些情况下,基于XML配置和基于Java配置的显式装配会有用武之地,比如实例化一个第三方库中的Bean.这种情况下,Java配置和XML配置我们优先使用Java配置,因为这是一种类型安全的方式,能够在编译时就尽早发现错误.
关于上述所说的类型安全可以这样理解:
如果使用字符串的形式,在xml中类名或其他硬编码方式提供的信息,在开发时是发现不了的,会在运行时抛出异常。而使用Java配置形式,类名或其他硬编码配置信息写错的话,编译时就会提示错误,比如Eclipse中就会提示找不到类的错误信息,这就避免了这种情况下的运行时异常,因此是更加安全的.
八、@Configuration 中使用@ Autowired 注解 IDE 报错
在 Spring Boot 项目中会用 @Configuration 注解来初始化配置, 这时可以通过 @autowired 自动注入封装好的model对象, 方便使用yml中的配置的数据。
这样做代码运行没问题,通过该对象也可以成功的获取yml配置文件中的数据,但是 IDE 却给出 “Could not autowird. No beans of'RedisConfig' type found.” 的错误提示。
原因估计是因为在项目的启动的最初阶段,IDE 还没有扫描到model类,无法发现对应的 bean ,于是就需要我们手动的给其指定需要扫描的包了。
@Autowired注解和启动自动扫描的三种方式(spring bean配置自动扫描功能的三种方式)的更多相关文章
- spring Bean配置的三种形式
Spring Bean配置有以下三种形式: 传统的xml配置 Spring 2.5 以后新增注解配置 Spring3.0以后新增JavaConfig 1. 传统的xml配置 <?xml vers ...
- [原创]java WEB学习笔记103:Spring学习---Spring Bean配置:基于注解的方式(基于注解配置bean,基于注解来装配bean的属性)
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Spring3实战第二章第一小节 Spring bean的初始化和销毁三种方式及优先级
Spring bean的初始化和销毁有三种方式 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法: 优先级第二通过 <bean& ...
- Spring 学习笔记(三):Spring Bean
1 Bean配置 Spring可以看做是一个管理Bean的工厂,开发者需要将Bean配置在XML或者Properties配置文件中.实际开发中常使用XML的格式,其中<bean>中的属性或 ...
- 关于 spring MVC 配置自动扫描中 use-default-filters 属性
1.springMVC 设置扫描 Bean 的两种常见写法 1.1.先看第一种常见的配置:默认 <!-- 配置Controller扫描 --> <context:component- ...
- 两种流行Spring定时器配置:Java的Timer类和OpenSymphony的Quartz
1.Java Timer定时 首先继承java.util.TimerTask类实现run方法 import java.util.TimerTask; public class EmailReportT ...
- Spring Bean配置加载为BeanDefinition全过程(注解配置)
生产中有很多形式的的配置方式,本文仅分析注解配置.对于其他形式的配置区别主观以为主要在配置文件的解析过程不同,不一一分析了.本文以利用Dubbo框架开发rpc服务端为例详细阐述配置类的解析.数据保存. ...
- spring mvc配置datasource数据源的三种方式
2.使用org.apache.commons.dbcp.BasicDataSource 说明:这是一种推荐说明的数据源配置方式,它真正使用了连接池技术 <bean id="dataSo ...
- Spring中配置DataSource数据源的几种选择
从JNDI获得DataSource. 从第三方的连接池获得DataSource. 使用DriverManagerDataSource获得DataSource. 一.从JNDI获得DataSource ...
随机推荐
- PS 基础知识 渐变编辑器如何使用
ps渐变编辑器在哪 [ 标签:渐变,ps 渐变,编辑器 ] _______志 敏 回答:3 人气:9 解决时间:2009-04-16 15:28 满意答案 你先点渐变工具 然后左上出现渐变条设置 如图 ...
- maximum-depth-of-binary-tree——找出数的最大深度
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...
- android客户端向服务器端验证登陆方法的实现2
一.在上一篇文章中,我只是提到了其中一种方法来实现登陆 大家可以参见: http://www.apkbus.com/android-45004-1-1.html android获取web服务 ...
- Web框架Django(二)
一.Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层 ...
- 基于django做增删改查组件,分页器组件
增删改查组件 一.Djangoadmin的启发 二.基于Djangoadmin实现数据的增删改查 分页器组件 分页器组件的介绍以及源码解读 补充:源码下载,
- LeetCode215:Kth Largest Element in an Array
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- Finder 快捷键
记录几个常用的 Finder 快捷键: 复制 Finder 里选中的路径:option+cmd+c 地址栏跳到指定路径:shift+cmd+g 增加标签:cmd+t 显示/隐藏 标签栏:shift+c ...
- Asp.Net Core 初探 (三)
昨天失败的生产环境部署就先放着,明天再解决! 今天利用中午的空余时间看了一下Asp.net core 的Areas . 相对于Asp.net MVC5 以及之前的版本,asp.net core 的Ar ...
- 【BZOJ3782】上学路线 组合数+容斥+CRT
[BZOJ3782]上学路线 Description 小C所在的城市的道路构成了一个方形网格,它的西南角为(0,0),东北角为(N,M).小C家住在西南角,学校在东北角.现在有T个路口进行施工,小C不 ...
- EasyDarwin开源团队招募开发组成员
EasyDarwin开源流媒体服务器项目招募开发组成员,共同更新和维护EasyDarwin流媒体服务器,决策EasyDarwin后续开发方向: 加入要求: 1.对开源流媒体项目有浓厚兴趣: 2.有一定 ...