有Bean得治

  任何一个正常程序的访问都会在内存中创建非常多的对象,对象与对象之间还会出现很多依赖关系(一个处理业务逻辑的类中几乎都会使用到别的类的实例),一般的做法都是使用new关键字来创建对象,对于多次重复使用的对象会采用单例模式来设计。

  但在Spring中却不是这样,Spring框架使用了一个容器对这些对象进行管理,每一个需要被管理的对象被称为Bean,而管理这些Bean的容器,被称为IoC容器。

  控制反转(IoC)在是一种通过描述来生成或者获取对象的技术,在Spring Boot中,我们经常是通过注解来创建对象,这里只谈注解,无视XML。

  Spring Boot在启动的过程中,会去扫描需要被管理的Bean,将Bean装载到IoC容器中,根据依赖关系进行实例化对象,最后进行依赖注入。也就是说,在项目启动完成后,所有的Bean都已经实例化完成,并已在相应的地方注入完成,访问程序使用到的这些对象都只是在直接调用对象实例,并不会出现一个new的过程,因为这些对象在项目启动的时候就已经都被new出来了。

  Bean的创建方式有很多种,最常用的是@Component,@Service,@Repository等等直接放在类头上的注解,都是一些标记,用于被收集后反射再实例化最终赋值达到注入的目的,可了解的应该就是其中的一些附带规则:条件装配,就是如果存在某个Bean时(也可以判断不存在时)再装配当前这个Bean,不过条件装配我觉得应用场景并不常见。

  这里主要是要挖一挖@Bean这个注解的使用。

用@Bean创建Bean

  @Bean注解是只能用在方法上,标志该方法需要创建一个Bean,方法返回的对象就是创建Bean的目标对象。

建一个User实体类:

public class User {
private int id = 2;
private String name = "我是User类的小光";
private String sex = "我是难的"; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}

示例:

@Configuration  
public class Config {
@Bean
public String aaa(){
return "你大爷";
} @Bean
public User bbb(){
return new User();
}
}  

  这个Config类,创建了两个Bean,创建的对象一个是String对象一个是User对象,可以是任何对象,我这里为了更加直白的表达“Bean”是什么东西,特意使用了String来做例子。

当然了  bean的名字是可以定的 以下三种定义方式都可以:

    @Bean(name = "aaa")
@Bean("aaa")
@Bean

第三种方式没有指定名字,那么框架会将方法名作为bean的名字,注意:是方法原名,不会是小驼峰,只有应用在类上的注解创建的bean才会是小驼峰,@Bean是方法上的注解。

你的脑补绝对有用

  此时,你可以脑补一下框架是怎么创建Bean的:

        HashMap map = new HashMap();
map.put("aaa",new String("你大爷"));
map.put("bbb",new User());

  所谓IoC容器,就是一个集合,装了很多对象,你要用哪个对象,Spring就会从集合里取给你。

----->当然了,虽然你的脑补不一定完全正确,但是你的脑补绝对有用。

@Bean注解受不受@ComponentScan的影响?

  @ComponentScan注解定义扫描路径,也就是说,Spring Boot只会扫描指定路径之内的类,遇到特殊注解就会开始进行Bean的收集工作。

  在Spring Boot的启动类main方法上有@SpringBootApplication注解,点进去之后可以看到它里面包含的有@ComponentScan,所以尽管我们没有手动指定扫描范围,但是默认是以启动类所在的包作为一个扫描范围。

  但这里要说明的是,@ComponentScan这个注解,它是用来约束@Configuration,@Controller,@Service,@Repository,@Component等作用在类上注解,但是它管不了@Bean注解,只要项目中有@Bean注解,即使身处启动类的外层,不在@ComponentScan的扫描范围之内,该Bean也会存在,只是没有被扫描装配,也就是可以获取,但无法注入。

是否一定要和@Configuration一起用?

  我的答案是:是的!

  如果你没有加@Configuration注解,那么Spring将不会扫描这个类,但是你后期获取该Bean的时候,Spring可以找到它,也就是说,如果没有加@Configuration注解,那么项目启动后是没有该Bean的,只有当你获取该Bean的时候,才会进行实例化。

获取你的Bean

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Object aaa = context.getBean("aaa");
System.out.println(aaa.toString()); Object bbb = context.getBean("bb");
System.out.println(bbb.toString()); 

该示例代码获取的是Config类中的aaa和bbb两个Bean。

  注意,它并不是获取容器中的Bean,它是根据你提供的class和Bean名称跑去执行了一下方法,新new了一个对象给你,再有,这个Bean名称必须用原名,大小写不打折的。

  小提示:无论类的头上有没有@Configuration注解,该方式都可以成功,当然,如果类的头上有@Configuration注解,那么该Bean的返回对象可以直接在别处进行注入。

如果你要获取类上的Bean,可以采用下面这个工具类来获取:

@Component
public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext = null; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (null == SpringUtil.applicationContext) {
SpringUtil.applicationContext = applicationContext;
}
} // 获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
} // 通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
} // 通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
} // 通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}  

挖一挖@Bean这个东西的更多相关文章

  1. 挖一挖C#中那些我们不常用的东西之系列(3)——StackTrace,Trim

    时间太快了,三月又要过去了,告别一下...继续期待生死未卜的四月,今天我们继续挖一挖. 一: Environment.StackTrace 可能我们看到最多的就是catch中的e参数,里面会有一个St ...

  2. 挖一挖不常用到而又很实用的重载-Split

    Split这个基本上所有的程序开发人员都用到,一般使用单字符和长字符串拆分字符串的较多,其实还有一个重载非常好用,那就是多种组合字符来进行拆分. 例如: "aaaaaaaaaa{@}bbbb ...

  3. 挖一挖不常用到而又很实用的重载-Trim

    这个我想没有那个开发人员说不知道,但是里面有一个重载,这个不知道有多少开发人员知道! 可以看到,我可以去掉字符串前后的指定字符,只要我在char[]中指定即可,而不是仅仅去掉空格,这次为什么要提它,是 ...

  4. ArcGIS案例学习笔记-批处理擦除挖空挖除相减

    ArcGIS案例学习笔记-批处理擦除挖空挖除相减 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:批处理擦除.挖空.挖除.相减 数据源:chp13/ex5/pa ...

  5. ArcGIS案例学习笔记-手动编辑擦除挖空挖除相减

    ArcGIS案例学习笔记-手动编辑擦除挖空挖除相减 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:手动编辑擦除.挖空.挖除.相减 1. 选中内部要素 2. c ...

  6. 挖一挖不经常使用到而又非常有用的重载-Split

    Split这个基本上全部的程序开发者都用到,一般使用单字符和长字符串拆分字符串的较多.事实上另一个重载很好用.那就是多种组合字符来进行拆分. 比如: "aaaaaaaaaa{@}bbbbbb ...

  7. 挖一挖C#中那些我们不常用的东西之系列(2)——IsXXX 系列方法

    不知道有人做没做过对日外包,如果做过的话,那么对vb.net应该非常熟悉了,当年我刚毕业的时候也做过四个月的外包,那种日子简直 不是人过的,就连大楼下面买珠宝的阿姨都说,这些孩子,只看过他们上班,就没 ...

  8. 挖一挖C#中那些我们不常用的东西之系列(1)——ToDictionary,ToLookup

    这个系列我们看看C#中有哪些我们知道,但是又不知道怎么用,又或者懒得去了解的东西,比如这篇我们要介绍的toDictionary 和ToLookup. 从图中我们看到有四个ToXXX的方法,其中ToAr ...

  9. 挖一挖C#中那些我们不经常使用的东西之系列(1)——ToDictionary,ToLookup

    这个系列我们看看C#中有哪些我们知道.可是又不知道怎么用.又或者懒得去了解的东西,比方这篇我们要介绍的toDictionary 和ToLookup. 从图中我们看到有四个ToXXX的方法,当中ToAr ...

随机推荐

  1. 1.1 为什么要使用lambda 表达式

    第1章 lambda 表达式 1.1 为什么要使用lambda 表达式 1.2 lambda 表达式的语法 1.3 函数式接口 1.4 方法引用 1.5 构造器引用 1.6 变量作用域 1.7 默认方 ...

  2. BZOJ_1212_[HNOI2004]L语言_哈希

    BZOJ_1212_[HNOI2004]L语言_哈希 Description 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写 ...

  3. BZOJ 1412 狼和羊的故事

    首先,题目目的就是为了分割狼群和羊群,即建立超级源和超级汇求最小割从而转化成用网络流来处理. 如果没有空地,那么就是简单的二分图最大匹配,但是题中有空地的出现,所以需要在点与点之间建立双向边(不算后向 ...

  4. JAVA中正则表达式总结

    昨天,我的朋友请教我正则表达式.我也好久没有写过正则表达式了,昨天刚好看了下如鹏网创始人杨中科老师关于正则表达式的讲解.使我加深了正则表达式的印像.现我把他总结下: 许多语言,包括Perl.PHP.P ...

  5. C#多线程中的异常处理

    常规Thread中处理异常 使用Thread创建的子线程,需要在委托中捕捉,无法在上下文线程中捕捉 static void Main(string[] args) { ThreadStart thre ...

  6. zookeeper源码 — 二、集群启动—leader选举

    上一篇介绍了zookeeper的单机启动,集群模式下启动和单机启动有相似的地方,但是也有各自的特点.集群模式的配置方式和单机模式也是不一样的,这一篇主要包含以下内容: 概念介绍:角色,服务器状态 服务 ...

  7. SQL Server 容易忽略的错误

    一.概述 因为每天需要审核程序员发布的SQL语句,所以收集了一些程序员的一些常见问题,还有一些平时收集的其它一些问题,这也是很多人容易忽视的问题,在以后收集到的问题会补充在文章末尾,欢迎关注,由于收集 ...

  8. C语言sprintf和sscanf函数用法

    以前刚用C语言的时候,觉得字符串很难处理,后来用多了,发现其实并非如此,C语言也提供了许多函数给程序员使用.今天记录一下两个常用的两个字符串处理函数:sprintf和sscanf 1. sprintf ...

  9. linux根目录下的各文件夹含义说明

    在早期的 UNIX 系统中,各个厂家各自定义了自己的 UNIX 系统文件目录,比较混乱. Linux 面世不久后,对文件目录进行了标准化,于1994年对根文件目录做了统一的规范, 推出 FHS ( F ...

  10. HttpServletRequest 接口、HttpServletResponse 接口、请求转发与重定向

    上篇文章我们讲了servlet的基本原理,这章将讲一下剩余的部分. HttpServletRequest 接口 该接口是 ServletRequest 接口的子接口,封装了 HTTP 请求的相关信息, ...