}
@Bean
public Service3 service3() {
return new Service3();
}
}
上面是一个spring的配置类,类中3个方法定义了3个bean
@1:这个地方使用了@DependsOn,表示service1这个bean创建之前,会先创建好service2和service3
来个测试用例
@Test
public void test4() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig4.class);
System.out.println(context.getBean(com.javacode2018.lesson001.demo27.test4.Service1.class));
}
运行输出
create Service2
create Service3
create Service1
com.javacode2018.lesson001.demo27.test4.Service1@6e20b53a
@ImportResource:配置类中导入bean定义的配置文件
用法
有些项目,前期可能采用xml的方式配置bean,后期可能想采用spring注解的方式来重构项目,但是有些老的模块可能还是xml的方式,spring为了方便在注解方式中兼容老的xml的方式,提供了@ImportResource注解来引入bean定义的配置文件。
bean定义配置文件:目前我们主要介绍了xml的方式,还有一种properties文件的方式,以后我们会介绍,此时我们还是以引入bean xml来做说明。
看一下这个注解的定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ImportResource {
@AliasFor(“locations”)
String[] value() default {};
@AliasFor(“value”)
String[] locations() default {};
Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;
}
通常将其用在配置类上。
有3个参数:
- value和locations效果一样,只能配置其中一个,是一个string类型的数组,用来指定需要导入的配置文件的路径。
- reader:用来指定bean定义的读取器,目前我们知道的配置bean的方式有xml文件的方式,注解的方式,其实还有其他的方式,比如properties文件的方式,如果用其他的方式,你得告诉spring具体要用那种解析器去解析这个bean配置文件,这个解析器就是BeanDefinitionReader,以后我们讲BeanDefinition的时候再细说。
资源文件路径的写法
通常我们的项是采用maven来组织的,配置文件一般会放在resources目录,这个目录中的文件被编译之后会在target/classes目录中。
spring中资源文件路径最常用的有2种写法:
-
以classpath:开头:检索目标为当前项目的classes目录
-
以classpath*:开头:检索目标为当前项目的classes目录,以及项目中所有jar包中的目录,如果你确定jar不是检索目标,就不要用这种方式,由于需要扫描所有jar包,所以速度相对于第一种会慢一些
那我们再来说classpath:和classpath*:后面的部分,后面的部分是确定资源文件的位置地方,几种常见的如下:
相对路径的方式
classpath:com/javacode2018/lesson001/demo27/test5/beans.xml
或者
classpath*:com/javacode2018/lesson001/demo27/test5/beans.xml
/:绝对路径的方式
classpath:/com/javacode2018/lesson001/demo27/test5/beans.xml
*:文件通配符的方式
classpath:/com/javacode2018/lesson001/demo27/test5/beans-*.xml
会匹配test5目录中所有以beans-开头的xml结尾的文件
*:目录通配符的方式
classpath:/com/javacode2018/lesson001/demo27//beans-.xml
会匹配demo27中所有子目录中所有以beans-开头的xml结尾的文件,注意这个地方只包含demo27的子目录,不包含子目录的子目录,不会进行递归
**:递归任意子目录的方式
classpath:/com/javacode2018/**/beans-*.xml
**会递归当前目录以及下面任意级的子目录
ok,继续回到@ImportResource上来,来看案例
案例代码
来2个类,这两个类我们分别用2个xml来定义bean
ServiceA
package com.javacode2018.lesson001.demo27.test5;
public class ServiceA {
}
ServiceB
package com.javacode2018.lesson001.demo27.test5;
public class ServiceB {
}
beans1.xml来定义serviceA这个bean,如下
<?xml version="1.0" encoding="UTF-8"?><beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
beans2.xml来定义serviceB这个bean,如下
<?xml version="1.0" encoding="UTF-8"?><beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
下面来个配置类,来引入上面2个配置文件
package com.javacode2018.lesson001.demo27.test5;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ImportResource;
@Configurable
@ImportResource(“classpath:/com/javacode2018/lesson001/demo27/test5/beans*.xml”)
public class MainConfig5 {
}
这个类上使用了@Configurable表示这是个配置类
并且使用了@ImportResource注解来导入上面2个配置文件
来个测试用例加载上面这个配置类
@Test
public void test5() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig5.class);
for (String beanName : context.getBeanDefinitionNames()) {
System.out.println(String.format(“%s->%s”, beanName, context.getBean(beanName)));
}
}
上面会输出MainConfig5配置类中所有定义的bean
运行输出
mainConfig5->com.javacode2018.lesson001.demo27.test5.MainConfig5@4ec4f3a0
serviceA->com.javacode2018.lesson001.demo27.test5.ServiceA@223191a6
serviceB->com.javacode2018.lesson001.demo27.test5.ServiceB@49139829
从输出中可以看出2个xml中定义的bean也被注册了
@Lazy:延迟初始化
用法
@Lazy等效于bean xml中bean元素的lazy-init属性,可以实现bean的延迟初始化。
所谓延迟初始化:就是使用到的时候才会去进行初始化。
来看一下其定义:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
boolean value() default true;
}
可以用在任意类型、方法、构造器、参数、字段上面
参数:
value:boolean类型,用来配置是否应发生延迟初始化,默认为true。
常用3种方式
-
和@Compontent一起标注在类上,可以是这个类延迟初始化
-
和@Configuration一起标注在配置类中,可以让当前配置类中通过@Bean注册的bean延迟初始化
-
和@Bean一起使用,可以使当前bean延迟初始化
来看一下这3种方式案例代码。
案例1:和@Compontent一起使用
Service1
package com.javacode2018.lesson001.demo27.test6;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy //@1
public class Service1 {
public Service1() {
System.out.println(“创建Service1”);
}
}
@1:使用到了@Lazy,默认值为true,表示会被延迟初始化,在容器启动过程中不会被初始化,当从容器中查找这个bean的时候才会被初始化。
配置类
package com.javacode2018.lesson001.demo27.test6;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class MainConfig6 {
}
测试用例
@Test
public void test6() {
System.out.println(“准备启动spring容器”);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
System.out.println(“spring容器启动完毕”);
System.out.println(context.getBean(com.javacode2018.lesson001.demo27.test6.Service1.class));
}
运行输出
准备启动spring容器
spring容器启动完毕
创建Service1
com.javacode2018.lesson001.demo27.test6.Service1@4fb61f4a
可以看出service1这个bean在spring容器启动过程中并没有被创建,而是在我们调用getBean进行查找的时候才进行创建的,此时起到了延迟创建的效果。
案例2:和@Configuration一起使用加在配置类上
@Lazy和@Configuration一起使用,此时配置类中所有通过@Bean方式注册的bean都会被延迟初始化,不过也可以在@Bean标注的方法上使用@Lazy来覆盖配置类上的@Lazy配置,看下面代码:
配置类MainConfig7
package com.javacode2018.lesson001.demo27.test7;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
@Lazy //@1
@Configurable
public class MainConfig7 {
@Bean
public String name() {
System.out.println(“create bean:name”);
return “路人甲Java”;
}
@Bean
public String address() {
System.out.println(“create bean:address”);
return “上海市”;
}
@Bean
@Lazy(false) //@2
public Integer age() {
System.out.println(“create bean:age”);
return 30;
}
}
@1:配置类上使用了@Lazy,此时会对当前类中所有@Bean标注的方法生效
@2:这个方法上面使用到了@Lazy(false),此时age这个bean不会被延迟初始化。其他2个bean会被延迟初始化。
测试用例
@Test
public void test7() {
System.out.println(“准备启动spring容器”);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig7.class);
System.out.println(“spring容器启动完毕”);
for (String beanName : Arrays.asList(“name”, “age”, “address”)) {
System.out.println(“----------”);
System.out.println(“getBean:” + beanName + “,start”);
System.out.println(String.format(“%s->%s”, beanName, context.getBean(beanName)));
System.out.println(“getBean:” + beanName + “,end”);
}
}
上面会输出配置类中定义的3个bean的信息。
运行输出
准备启动spring容器
create bean:age
spring容器启动完毕
getBean:name,start
create bean:name
name->路人甲Java
getBean:name,end
getBean:age,start
age->30
getBean:age,end
getBean:address,start
create bean:address
address->上海市
getBean:address,end
输出中可以看到age是在容器启动过程中创建的,其他2个是在通过getBean查找的时候才创建的。
总结
–
-
本文介绍的几个注解也算是比较常用的,大家一定要熟悉他们的用法
-
@Scope:用来定义bean 的作用域;2种用法:第1种:标注在类上;第2种:和@Bean一起标注在方法上
-
@DependsOn:用来指定当前bean依赖的bean,可以确保在创建当前bean之前,先将依赖的bean创建好;2种用法:第1种:标注在类上;第2种:和@Bean一起标注在方法上
-
@ImportResource:标注在配置类上,用来引入bean定义的配置文件
-
@Lazy:让bean延迟初始化;常见3种用法:第1种:标注在类上;第2种:标注在配置类上,会对配置类中所有的@Bean标注的方法有效;第3种:和@Bean一起标注在方法上
案例源码
https://gitee.com/javacode2018/spring-series
路人甲java所有案例代码以后都会放到这个上面,大家watch一下,可以持续关注动态。
Spring系列
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-gJeSknPL-1711997394293)]
[外链图片转存中…(img-mPGota6G-1711997394294)]
[外链图片转存中…(img-HMpBw1ci-1711997394294)]
[外链图片转存中…(img-lTk9V39O-1711997394294)]
[外链图片转存中…(img-cKgM1vTI-1711997394295)]
[外链图片转存中…(img-ao8amsca-1711997394295)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-DEdODLuQ-1711997394295)]
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
[外链图片转存中…(img-wp0mO4Ok-1711997394296)]
[外链图片转存中…(img-rsoNJA0z-1711997394296)]
[外链图片转存中…(img-3Qj1kUve-1711997394296)]