Spring之自动装配

​ Spring利用依赖注入(DI),完成对IOC容器中各个组件依赖关系的赋值。

【1】@Autowired

@Autowired 注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。

通过 @Autowired的使用来消除 set ,get方法。在使用@Autowired之前,我们对一个bean配置其属性时,是这样做的:

<property name="属性名" value="属性值"/>

通过这种方式来,配置比较繁琐,而且代码比较多。在Spring 2.5 引入了 @Autowired 注解。

由于该注解比较简单,这里就不再用代码举例说明了,主要来说一下@Autowired的原理和使用它的注意事项。

那么使用@Autowired的原理是什么?

​ 其实在启动Spring容器时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IOC容器自动查找需要的bean,并装配给该对象的属性。

这里说明一下@Resource和@Inject这两个注解:

@Resource是通过JSR250规范实现的,通过CommonAnnotationBeanPostProcessor类实现依赖注入

@Inject是通过JSR330规范实现的,通过AutowiredAnnotationBeanPostProcessor类实现的依赖注入

三个注解的相异之处:

@Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理依赖注入。但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。当然,两者都是BeanPostProcessor。

​ @Resource默认是按照组件名称进行装配的,不能支持@Primary(标注在配置类的Bean上,在自动注入时优先注入该Bean)和@Autowired(required=false)功能

​ @Inject需要导入javax.inject包,和@Autowired功能一样,不支持@Autowired(required=false)功能

@Autowired可以标注的位置:

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}

​ 标注到构造器、参数、方法、属性都是从容器中获取参数组件的值

  • 构造器:如果当前类只有一个有参构造器,这个有参构造器上的@Autowired可以省略。
  • 方法:在标注@Bean注解的方法上,参数可以不用标注@Autowired注解,也会自动从容器中获取。

【2】Aware

​ Spring的依赖注入的最大亮点就是你所有的Bean对Spring容器的存在是没有意识的。即你可以将你的容器替换成别的容器,例如Goggle Guice,这时Bean之间的耦合度很低。

​ 但是在实际的项目中,我们不可避免的要用到Spring容器本身的功能资源,这时候Bean必须要意识到Spring容器的存在,才能调用Spring所提供的资源,这就是所谓的Spring Aware。其实Spring Aware本来就是Spring设计用来框架内部使用的,若使用了Spring Aware,你的Bean将会和Spring框架耦合。

​ 比如BeanNameAware、BeanFactoryAware、ApplicationContextAware接口。假设我们的类继承了BeanNameAware这个接口,对应这个接口有一个方法setBeanName的方法,spring在依赖注入的初始化阶段会调用生成对象的这个方法,把beanName传为入参传进来。一般我们在会自己写的类里面定义一个属性来接收这个beanName,然后这个beanName我们就可以在开发中使用了。

​ 常用的Aware接口:

Aware子接口 描述
BeanNameAware 获取容器中 Bean 的名称
BeanFactoryAware 获取当前 BeanFactory
ApplicationContextAware 获取当前容器
MessageSourceAware 与国际化相关
ApplicationEventPublisherAware 主要用于发布事件
ResourceLoaderAware 获取资源加载器,这样获取外部资源文件

​ 下面以实现BeanNameAware为例:

public class Person implements BeanNameAware {
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Person() {
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
} @Override
public void setBeanName(String s) {
this.name = s;
}
}

​ 在配置类中注入Person

@Configuration
public class MyConfig {
@Bean("Jack")
public Person person(){
return new Person();
}
} /**在测试类中获取该Bean并打印
Person{name='Jack'}
*/

【3】@Profile

1.Spring中的@Profile 是什么?

​ Spring中的Profile功能其实早在Spring 3.1的版本就已经出来,它可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring容器中。举个更具体的例子,我们以前所定义的Bean,当Spring容器一启动的时候,就会一股脑的全部加载这些信息完成对Bean的创建;而使用了Profile之后,它会将Bean的定义进行更细粒度的划分,将这些定义的Bean划分为几个不同的组,当Spring容器加载配置信息的时候,首先查找激活的Profile,然后只会去加载被激活的组中所定义的Bean信息,而不被激活的Profile中所定义的Bean定义信息是不会加载用于创建Bean的。

2.@Profile如何使用

​ 下面我们定义两个数据源,分别使用@Profile注解指定在测试和开发阶段使用

@Configuration
public class MyConfig {
@Bean
@Profile("test")
public DataSource dataSourceTest() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.driver");
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setUser("root");
dataSource.setPassword("root");
return dataSource;
}
@Bean
@Profile("dev")
public DataSource dataSourceDev() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.driver");
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setUser("root");
dataSource.setPassword("root");
return dataSource;
}
}

​ 在测试类中我们设置当前激活环境为test:

public class ProfileTest {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.setActiveProfiles("test");
applicationContext.register(MyConfig.class);
applicationContext.refresh();
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
} /**测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
dataSourceTest
*/

​ 在当前环境为test环境时,只有dataSourceTest被注入到容器当中。

​ @Profile不仅可以标注到方法上面,还可以标注到类上,即整个类根据环境进行加载。

五、Spring之自动装配的更多相关文章

  1. spring的自动装配,骚话@Autowired的底层工作原理

    前言 开心一刻 十年前,我:我交女票了,比我大两岁.妈:不行!赶紧分! 八年前,我:我交女票了,比我小两岁,外地的.妈:你就不能让我省点心? 五年前,我:我交女票了,市长的女儿.妈:别人还能看上你?分 ...

  2. spring注解-自动装配

    Spring利用依赖注入(DI)完成对IOC容器中中各个组件的依赖关系赋值 一.@Autowired 默认优先按照类型去容器中找对应的组件(applicationContext.getBean(Boo ...

  3. Spring的自动装配Bean

    spring的自动装配功能的定义:无须在Spring配置文件中描述javaBean之间的依赖关系(如配置<property>.<constructor-arg>).IOC容器会 ...

  4. spring完成自动装配

    让spring完成自动装配 Autowiring 解决标签为javaBean注入时难以维护而实现的 下面是几种autowire type的说明: 1,byname:试图在容器中寻找和需要自动装配的属性 ...

  5. spring中自动装配bean

    首先用@Component注解类: package soundsystem: import org.springframework.stereotype.Component; @Component p ...

  6. Spring Boot 自动装配(二)

    目录 目录 前言 1.起源 2.Spring Boot 自动装配实现 2.1.@EnableAutoConfiguration 实现 2.1.1. 获取默认包扫描路径 2.1.2.获取自动装配的组件 ...

  7. Eureka 系列(03)Spring Cloud 自动装配原理

    Eureka 系列(03)Spring Cloud 自动装配原理 [TOC] 0. Spring Cloud 系列目录 - Eureka 篇 本文主要是分析 Spring Cloud 是如何整合 Eu ...

  8. Spring Boot自动装配

    前言 一些朋友问我怎么读源码,这篇文章结合我看源码时候一些思路给大家聊聊,我主要从这三个方向出发: 确定目标,这个目标要是一个具体,不要一上来我要看懂Spring,这是不可能的,目标要这么来定,比如看 ...

  9. Spring Boot自动装配原理源码分析

    1.环境准备 使用IDEA Spring Initializr快速创建一个Spring Boot项目 添加一个Controller类 @RestController public class Hell ...

随机推荐

  1. Unity TextMeshPro替代Text组件创建简体中文字体纹理集

    Unity原生的Text组件有一个毛病,只要文本放大字体放大就会有毛边或锯齿,一个更好的解决方案是用TextMeshPro替代ugui中的Text组件. TMPro采用SDF文字渲染技术,可以使文字放 ...

  2. RPA中房产证的 OCR 识别

    客户需求,识别一些证件内容,包括身份证.户口本.营业执照.银行卡以及房产证,前四个比较容易实现,不管是艺赛旗的 RPA 还是百度的 OCR 都有接口,直接调用即可,但是都没有房产证的 OCR 识别,只 ...

  3. VS2019 MSB364 未找到框架“NETFramework,Version=v4.7”

    环境: WIN 10 VS2019 已安装框架v4.7.2 问题: 在打开一些早期项目时,编译报 MSB364 错误,未找到框架“NETFramework,Version=v4.7”或未找到框架“NE ...

  4. mysql中的ifnull()函数判断空值

    我们知道,在不同的数据库引擎中,内置函数的实现.命名都是存在差异的,如果经常切换使用这几个数据库引擎的话,很容易会将这些函数弄混淆. 比如说判断空值的函数,在Oracle中是NVL()函数.NVL2( ...

  5. Web前端基础(3):HTML(三)

    1. body中的相关标签 1.1 表格标签:table.tr.td HTML表格由<table>标签以及一个或多个<tr>.<th>或<td>标签组成 ...

  6. linux tmux用法

    1. 安装工具 Centos : yum install tmux 2. 基本操作 新建会话:tmux new -s session-name 查看会话:tmux ls 进入会话:tmux a -t  ...

  7. 阿里云centos7安装python3.7.4和pip3

    亲测有效,针对 阿里云 centos 7 轻量服务器 python ==> 3.7.4 pip ==>  3 一,打开python官网,找到下载Python的tgz文件,有两种方式下载 ( ...

  8. ABP进阶教程0 - 目录

    ABP进阶教程 本教程主要讲解如何基于ABP实现条件查询/分页/排序/导出/打印等功能. 源码已分享:   GitHub   Gitee ABP进阶教程0 - 目录 ABP进阶教程1 - 条件查询 A ...

  9. 熟悉的味道——从Java单例写到C++单例

    设计模式中,单例模式是常见的一种.单例模式需要满足以下两个条件: 保证一个类只能创建一个示例: 提供对该实例的全局访问点. 关于单例最经典的问题就是DCL(Double-Checked Lock),今 ...

  10. 获取SpringCloud gateway响应的response的值,记录踩坑

    最近在做网关改造,想要通过Gateway过滤器获取ResponseBody的值,查看了网上的帖子和官网内容: 帖子:https://cloud.tencent.com/developer/articl ...