@Configuration这个注解我想大家都不陌生吧,在大家看来加了@Configuration注解的类只不过是一个配置类,用来代替xml配置文件的一个类,在这个配置类里面可以和@Bean注解一起使用,通过@Bean注解往spring容器注入bean,简化了我们的开发。但是@Configurantion的作用真的是这样子的吗?话不多说就让我们一起来揭开@Configuration的真实身份。

public Class UserService{public UserService(){System.out.println("UserService init");}}public Class OrderSerivce{public OrderSerivce(){System.out.println("OrderSerivce init");}}@Configuration
public Class AppConfig{@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderSerivce orderSerivce(){return new OrderSerivce();}
}public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext ac = new     AnnotationConfigApplicationContext(AppConfig.class);}
}

我想大家对上面这些代码都很熟悉吧,和大家想的一样,这些代码是可以正常运行的没有问题。运行结果如下:

UserService init
OrderService initProcess finished with exit code 0

我们可以看到,UserService和OrderSerivce都成功的进行了初始化,被放到spring容器里面了,而起到这种作用的原因是因为我们在类上面加上了@Configuration注解,所以能扫描到加了@Bean的方法把对象注入到容器中。真的是这样吗?接下来我们把@Configuration注解重配置类上去掉

public Class AppConfig{@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderSerivce orderSerivce(){return new OrderSerivce();}
}public static void main(String[] args) {AnnotationConfigApplicationContext ac = new             AnnotationConfigApplicationContext(AppConfig.class);System.out.println(ac.getBean(UserService.class));
}

讲道理,当我们去掉了@Configuration注解,配置类就失效了,里面的UserService和OrderService就无法被注册到spring容器当中了。这是当我们通过getBean获取UserSerivce的时候就会出现异常,没有找到UserService这个bean。但是结果真的是这样吗?运行结果如下:

UserService init
OrderService init
com.zhijia.service.UserService@2833cc44Process finished with exit code 0

运行结果很明显,代码是可以正常运行的。UserService和OrderSerivce一样可以实例化到spring容器当中,通过getBean()也可以得到UserService打印到控制台。小伙伴们是不是不敢相信。你们可以直接手动去测试一下,代码是不会骗人的。

这个时候我们就会有个疑问,那我们还要@Configuration有何用?不要心急,我们学编程的时候要沉下心来。接下来我们就来揭开@Configuration的真实作用,让我们举个实例来分析。

public class AppConfig {@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderService orderService(){userService();return new OrderService();}}public static void main(String[] args) {AnnotationConfigApplicationContext ac = new             AnnotationConfigApplicationContext(AppConfig.class);}

上面我们在UserService里面调用OrderService这个时候UserSerivce会被调用两次,运行结果如下:

UserService init
UserService init
OrderService initProcess finished with exit code 0

那当我们在配置类上加上@Configuration的时候,那又是个什么样的结果呢?UserService会被实例化几次呢?

@Configuration
public class AppConfig {@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderService orderService(){userService();return new OrderService();}}public static void main(String[] args) {AnnotationConfigApplicationContext ac = new             AnnotationConfigApplicationContext(AppConfig.class);}

运行结果如下:

UserService init
OrderService initProcess finished with exit code 0

我们可以看到,UserService只被实例化了一次。按照我们java的语法来讲,我们这里调用了userService这个方法,调用这个方法它一定会实例化一次。但是但我们加上@Configuration注解的之后,你会发觉它只实例化了一次。

现在我们搞清楚了@Configuration主要是用来做什么的了吧,它就是为了能够让我们spring,比如所我们的springboot或者spring在写上这种@Bean注解的时候(利用Java Config注解来完成对spring环境开发的时候),保证bean的一个作用域,保证它(bean)的生命周期跟它的作用域,包括Scope,Scope就是我们讲的单例(singletion)和原型(prototype)。

那他是如何保证的呢,到这里我们来分析一个问题:

按照我们对java的理解,我们spring内部它要去实现这个UserService,它首先会调用一遍
下边这个userService()然后得到UserService。然后再去实例化我们OrderService的时候,
在OrderService里面调用又调用userService(),由于我们的代码中已经写死了,一定会去
new UserSerivce() 那么肯定会执行两遍构造方法。

@Configuration
public class AppConfig {/***  按照我们对java的理解,我们spring内部它要去实现这个UserService,它首先会调用一遍*  下边这个userService()然后得到UserService。然后再去实例化我们OrderService的时候,*  在OrderService里面调用又调用userService(),由于我们的代码中已经写死了,一定会去*  new UserSerivce() 那么肯定会执行两遍。*  */@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderService orderService(){userService();return new OrderService();}}

那么它没有执行两遍只有一个原因,你们可以思考一下,当我们一个方法调用的时候它的预期结果跟你想的不一样,那么你觉得是什么导致的。说白了,就是这个方法被改变了,这个方法不再是原来的这个方法,。因为我们这个方法,它的结果是必然的,它必然会产生一个类,但是我们调用两次它只产生一个类。那就违背了它的必然结果,那就说明了这个代码已经被别人改了。那么被随改了,肯定是被spring改了。那么按照我们现在所学的知识当中,我们要去改变一个方法的行为,没有改源码,可以用什么实现?

没错就是动态代理,在这里用的是cglib动态代理。同学们不相信是吧?那我就是通过代码跟大家证明一下。

现在我们配置类上是没有加@Configuration注解的,这时从容器中获取这个AppConfig这个配置类,你会发现这个类没有改变,他还是叫AppConfig。


public class AppConfig {@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderService orderService(){userService();return new OrderService();}}public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext ac = new             AnnotationConfigApplicationContext(AppConfig.class);AppConfig appConfig = ac.getBean(AppConfig.class);System.out.println(appConfig);}
}

运行结果如下:com.zhijia.config.AppConfig@2833cc44

UserService init
UserService init
OrderService initcom.zhijia.config.AppConfig@2833cc44Process finished with exit code 0

当我们加上@Configuration注解的时候,这时从容器中获取这个AppConfig这个配置类是一个cglib动态代理产生的类。

@Configuration
public class AppConfig {@Beanpublic UserService userService(){return new UserService();}@Beanpublic OrderService orderService(){userService();return new OrderService();}}public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext ac = new             AnnotationConfigApplicationContext(AppConfig.class);AppConfig appConfig = ac.getBean(AppConfig.class);System.out.println(appConfig);}
}

运行结果如下:很明显的五个大字母

  com.zhijia.config.AppConfig$$EnhancerBySpringCGLIB$$e52e37ff@588df31b

UserService init
OrderService initcom.zhijia.config.AppConfig$$EnhancerBySpringCGLIB$$e52e37ff@588df31bProcess finished with exit code 0

这下子就清楚底层是用什么实现了吧,大家可以手动自己去证实一下。由于底层代码写起来比较复杂,这里就简单跟大家提一下主要是用什么实现的,就不深入分析了,如果感兴趣的伙伴可以自己去研究一下源码。

之所以发布这篇文章就是想解决大家对@Configuration的一些误解。 如果本文对你有帮助的话,记得点个赞!谢谢大家!

HZJ,一个在学习路上匍匐前行的小菜鸟!

配置类不加@Configuration竟然也可以注册bean相关推荐

  1. Springboot 配置类( @Configuration) 不能使用@Value注解从application.propertyes中加载值以及Environment为null解决方案

    Springboot 配置类( @Configuration) 不能使用@Value注解从application.propertyes中加载值以及Environment为null解决方案 参考文章: ...

  2. 2字段添加注释_2w字长文给你讲透了配置类为什么要添加 @Configuration注解

    文章来源:https://mp.weixin.qq.com/s/5UvbeEnZBS7niAJw_f-6pQ 原文作者:程序员DMZ Spring 用的爽不爽?在你爽的同时,你也知道为什么这么爽,在 ...

  3. 配置类Configuration

    配置类@Configuration 01.概述 配置类:在springboot中被@Configuration或者@SpringBootConfiguration标注的类称之为配置类. 02.作用&a ...

  4. 2.3.3 spring属性注入-注解注入-全注解-配置类扫描

    代码: spring2-属性注入-全注解-配置类扫描.zip - 蓝奏云文件大小:12.3 K|https://www.lanzouw.com/iPK5vvq21uf 这个博客,我们使用全注解的方式来 ...

  5. [SpringBoot2]容器功能_底层注解配置绑定_@Configuration@Import@Conditional@ImportResource

    @Configuration&@Bean 告诉SpringBoot这是一个配置类==配置文件 #############################Configuration使用示例### ...

  6. @param注解的用法解析_SpringBoot 配置类解析

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/NvPO5-FWLiOlrsOf4wLaJA 作者:Li Wanghong SpringBoot ...

  7. SpringBoot -> 自动装配初探,debug=ture判断配置类是否生效

    文章目录 第一个注解:@SpringBootApplication 点进去有一堆注解: 1.这4个是元注解: 2.@SpringBootConfiguration @EnableAutoConfigu ...

  8. spring解析配置类

    我们知道spring在启动的过程中,会调用refresh()方法,而refresh()方法会调用invokeBeanFactoryPostProcessors(beanFactory):通过方法名称可 ...

  9. Spring(十三)- Spring 配置类的注解

    文章目录 一.Spring 配置类的注解 1. @Configuration 2. @ComponentScan 3. @PropertySource 4. @Import 二.Spring 配置其他 ...

最新文章

  1. Linux C编程一站式学习读书笔记——socket编程
  2. shell开发跳板机功能脚本
  3. SCCM 2007 R2部署、操作详解系列之部署篇
  4. mysql注入写一句话_Mysql注入root权限直接写一句话马
  5. python 自动发邮件 Errno61 Connection refused
  6. [转载]关于webbrowser,innet,xmlhttp获取网页源码的比较!
  7. JQuery在循环中绑定事件的问题详解
  8. navigationBar模块未绑定
  9. python中的列表推导与生成器
  10. RN:app开发入门指南
  11. hping3进行SYN Flood攻击
  12. 使用CSS和javascript制作拼图验证码
  13. 对《小王子》英文原版进行词频统计,发现他最爱的是......
  14. 一些RGB颜色值——笔记
  15. java会签_工作流引擎会签,加签,主持人,组长模式 专题讲解
  16. 淘宝-没素质的商家给消费者加入禁购名单
  17. linux 隐藏命令参数,linux – 在ps中隐藏命令的参数
  18. mc服务器地皮系统权限指令,我的世界地皮指令大全
  19. MAC无法挂载移动硬盘
  20. Redis常用命令入门4:集合类型

热门文章

  1. ES5ES6 day16
  2. Android中播放本地SD卡中歌曲需要的添加的权限
  3. Python plot() 画图标记 marker
  4. 【软件测试】如何测试人工智能软件?
  5. 归并排序(JAVA版)
  6. 高斯牛顿法----MATLAB实现
  7. 国密:SM2公私钥加签验签
  8. 多机Nomad+Consul+consul-template+Nginx反向代理
  9. 毕设 深度学习卷积神经网络的花卉识别
  10. Junit新语法assertThat