目录
一、引言
二、案例学习
(一)@Bean
(二)@Import
三、补充
(1)关于Java中collection.toArray(new String[0])解释
(2)组合注解
一、引言
- 上次学习了解到,springboot可以默认自动的扫描启动类所在的包及其子包
- 现在查看还有哪些注解会被扫描到并解析,从而把对应的Bean对象注册到Ioc容器中
- Bean对象的注册,在spring中学习过。可以添加下面这些注解,从而把该类对象注册到Ioc容器中。其中@Component注解是一个通用的。而其下面的@Controller、@Service、@Repository这三个注解是一个衍生注解,它们经常controller层、service层、dao层的类中,从而让代码的可读性更高
- 如果要把第三方的jar包中的Bean对象注入到Ioc容器中,上面的注解还能继续使用吗??答案不能,因为如下在导入的外部库里面找到一个jar包,然后进去找到一个类,想直接在上面注入对象,发现无法编辑(只读)。所有如果是第三方jar包的类的对应的对象,并不能在类上添加上面四个注解,然后把bean对象注入进去。
- 也就是如果要注册的Bean对象来自于第三方,或者这个类不是我们自定义的,是无法使用@Component及其衍生注解声明Bean的
- spring提供了两个注解来解决上面的问题
二、案例学习
(一)@Bean
(1)安装一个自己写的jar包到本地仓库,然后在工程里添加其依赖
(目标是把这个两个类的对应的Bean对象给它注入到Ioc容器中)
(2)现在开始尝试操作
- jar包中的两个实体类,Country、Province
- SpringApplication.run(...)方法会把spring初始化好的容器返回回来。这里可以用一个ApplicationContext context = SpringApplication.run(...),来接收一下容器。然后调用这个容器的方法getBean()去获取对象。
(3)但是一般不用上面的写法。
- 因为启动类里一般只做启动活,不要去做注册的事情。而是一般采用在配置类中集中注册。可以定义一个配置类,叫做CommonConfig。并且要将它变成配置类,就要添加一个注解@Configuration。
- 我们可以在配置类中声明一模一样的方法。在类上方添加注解@Configuration,在方法上添加一个注解@Bean。注意这个配置类,要放到启动类所在的包或子包中,才能被扫描到。
(4)再次尝试操作
- 新建包和类
- 在配置类添加注解和书写方法
- 注入对象的默认的名字是方法名(也可以通过注解@Bean("....")括号里指定的自定义名称)。这里在启动类中获取Ioc容器已经注册好的两个类的Bean对象。控制台全部都拿到了对应的对象并打印输出。
- 如果方法的内部需要使用到Ioc容器中已经存在的Bean对象,那么只需要在方法上声明即可,spring会自动的注入
(二)@Import
(1)我们可以在启动类添加注解@Import,导入其它类。spring会自动的把指定的类对应的Bean对象注入到Ioc容器中。且这个指定的类,可以是任意的类(普通类、配置类)。
(2)实际开发中,一般导入以下的两种类最多
(3)开始尝试操作
- 将之前启动类所在包的配置类移动到其它的包下,这样就会扫描不到。然后是不是之前在启动类就拿不到注册的Bean对象。这时就要用@Import注解。
- 当我们这样写了spring就会将CommonConfig配置类中已经注册好的Bean对象放到Ioc容器中
- 如果配置类很多,可以采用花括号里一个一个填(数组)解决
但是这样如果很长很多,不好看、不优雅。就会提到另外一个东西。
- springboot会自动调用selectImports()方法,得到里面的数组,然后把这些对应的类的Bean对象自动的注入到Ioc容器中
- 接着在启动类里就注解@Import不引入配置类了,而是引入实现类
- 其次在实现类里面的类名都是一般在配置文件中读取出来。(为了让程序变得更加灵活)需要哪些对象需要注入,就把这个对应的全类名写到配置文件中去就可以了。
- 去resources目录下创建配置文件
(这个文件中每一个类对应写一行就可以了)也就是有多个Bean对象需要注入,就换行写就行了。
- 现在就可以去CommonImportSelector实现类读取配置文件里的内容,用List集合接收。要通过类加载器来读取这个配置文件。类名.class.getClassLoader().getResourceAsStream("..."),括号里面写上面的配置文件名:"common.imports"。这个会得到一个输入流,然后给它进行一个封装(BufferedReader)得到一个缓冲字符流br。然后再创建一个变量,记录行数,一行一行的读取。读完之后记得关闭流(close)。会报错,try...catch一下即可(ctrl+alt+t)
- 最后return返回的就是集合imports里面读取到的数据。集合转换为数组(toArray(new String[0]))
- 最后完成启动工程验证了之后。发现还可以进行一些修改。让下面这个注解变成组合注解,变得更加好看
- 仿照启动类里面的组合注解的写法(复制粘贴)并介绍一下
第一个代表:当前这个注解可以再类上使用。第二个代表这个注解会保留在运行时间段。
- 最后回到启动类,再把之前的注解注释掉,书写新的组合注解
三、补充
(1)关于Java中collection.toArray(new String[0])解释
- String[] x = (String[]) v.toArray(new String[0]); 注意,toArray(new Object[0]) 和 toArray() 在功能上是相同的。
- <T> T[] toArray(T[] a),T:泛型。会返回你一个list长度的String 类型的数组,需要一个T[] a,new String[0]相当于开辟了一个长度为0的String[],并且指定了泛型。这样函数的调用是将list转换了一个String的数组。
- 这里的用new String[0]只是为了指定函数的形参数,最终返回的String[]的长度是由你的list存储内容的长度决定了。new String[0]就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型
- list.toArray(new String[0]);//转化成String数组
- list.toArray(new int[0]);//转化成int数组
此解释来源于csdn另外一篇(Java中collection.toArray(new String[0])的语法解释-CSDN博客)
(2)组合注解
这种情况经常会在第三方的起步依赖或者源码中看到。