Spring中的自动配置
1.区别管理和不管理的类
通过注解方式(想要管理的加上注解)
@Controller
控制器。 用于描述 web层的处理器。@Service
: 用于描述 服务层的对象。@Repository
: 用于描述 Dao层的对象。@Component
: 一般性的组件
以上注解对Spring管理,效果上没有任何差别,但是使用时最好根据语义来。
2.类之间的依赖关系
- 使用Spring提供的标准注解
@Autowired
- 使用Java标准的
@Resource
- 使用Java标准的
@Inject
(需要额外导入jar包)
3.开启自动配置的功能
- 跟注解有关的功能 ,导入 Spring 的
aop
模块- 下载地址:
链接:https://pan.baidu.com/s/1G3ro61zrEyDdjFzRBc8bSg
提取码:vbkr
- 下载地址:
- 在配置文件中使用
<context:component-scan>
来开启扫描
4.Bean配置案例
目录结构
在Spring 的xml中开启扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
//传入要扫描的路径
<context:component-scan base-package="com.example.spring"></context:component-scan>
</beans>
测试类
public class Demo1 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"com/example/spring/scan/spring-config.xml");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (int i = 0; i <beanDefinitionNames.length ; i++) {
System.out.println(beanDefinitionNames[i]);
}
}
}
4.1 Spring 自己的Bean
只要开启扫描后Spring 就会自动创建一些自己的Bean,结果如下:
4.2 自定义Bean
创建自己的Bean类
@Component
public class TestBean1 {
}
测试结果:
打印结果是类名首字母小写
4.3自定义修改Bean在容器中的名字
如果想要自定义Bean的名字可以在注解上进行传入
@Component(value = "aaa")
public class TestBean1 {
}
显示结果:
4.4 自定义Bean的scope属性
使用@Scpoe()注解
- singleton表示单例对象,
- prototype表示每创建一次都创建一个新的
@Scope("singleton")
@Component(value = "aaa")
public class TestBean1 {
}
测试
public class Demo1 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"com/example/spring/scan/spring-config.xml");
TestBean1 aaa1 = (TestBean1) context.getBean("aaa");
TestBean1 aaa2 = (TestBean1) context.getBean("aaa");
System.out.println(aaa1==aaa2);
}
}
显示结果:
4.5 指定生命周期方法
标签:
- @PostContruct
- @PreDestory
测试代码:
这里需要注意的是ApplicationContext 没有close方法,没办法正常关闭容器,只能使用子类ConfigurableApplicationContext
public class Demo1 {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"com/example/spring/scan/spring-config.xml");
TestBean1 aaa = (TestBean1) context.getBean("aaa");
context.close();
}
}
Bean代码:
Bean类Scope只能是单例,如果是prototype则容器关闭时不会执行end()方法
@Scope("singleton")
@Component(value = "aaa")
public class TestBean1 {
@PostConstruct
public void start(){
System.out.println("初始化方法");
}
@PreDestroy
public void end(){
System.out.println("销毁方法");
}
}
显示结果:
调整Scope为prototype显示结果:
5.简单依赖注入
简单属性注入
将外部配置文件的属性值注入
out-source.properties文件
string=sss
Bean
@Scope("singleton")
@Component(value = "aaa")
public class TestBean1 {
//指定外部文件属性值的名称
@Value("${string}")
private String string;
@PostConstruct
public void start(){
System.out.println("初始化方法");
}
@PreDestroy
public void end(){
//打印拿到的外部文件属性值
System.out.println(string);
System.out.println("销毁方法");
}
}
xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example.spring"></context:component-scan>
//指定要获取外部文件的路径
<context:property-placeholder location="com/example/spring/scan/out-source.properties"></context:property-placeholder>
</beans>
显示结果:
@Value标签内也支持SpEL表达式
@Scope("singleton")
@Component(value = "aaa")
public class TestBean1 {
//SpEL表达式
@Value("#{'ssss'.substring(2)}")
private String string;
@PostConstruct
public void start(){
System.out.println("初始化方法");
}
@PreDestroy
public void end(){
System.out.println(string);
System.out.println("销毁方法");
}
}
显示结果:
6.其他Bean的注入
- 使用Spring提供的注解@AutoWired
- 使用java标准的@Resource
创建一个新Bean
@Component
public class TestBean2 {
}
想要在TestBean1中作为成员变量引入有三种方式:
- 直接在变量声明时加注解
@Autowired //或者@Resource
private TestBean2 testBean2;
- 在setter方法上加注解
@Autowired //或者@Resource
public void setTestBean2(TestBean2 testBean2) {
this.testBean2 = testBean2;
}
- 在构造方法上加注解
只能使用 @Autowired不能使用@Resource
@Autowired
public TestBean1(TestBean2 testBean2) {
this.testBean2=testBean2;
}
TestBean1代码:
@Scope("singleton")
@Component(value = "aaa")
public class TestBean1 {
@Autowired
private TestBean2 testBean2;
// @Autowired
// public TestBean1(TestBean2 testBean2) {
// this.testBean2=testBean2;
// }
// @Autowired
// public void setTestBean2(TestBean2 testBean2) {
// this.testBean2 = testBean2;
// }
@Value("#{'ssss'.substring(2)}")
private String string;
@PostConstruct
public void start(){
System.out.println("初始化方法");
}
@PreDestroy
public void end(){
//在销毁前判定是否为空,不为空则表明注入成功
System.out.println(testBean2!=null);
System.out.println("销毁方法");
}
}
Demo1测试
public class Demo1 {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"com/example/spring/scan/spring-config.xml");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (int i = 0; i <beanDefinitionNames.length ; i++) {
System.out.println(beanDefinitionNames[i]);
}
TestBean1 aaa = (TestBean1) context.getBean("aaa");
context.close();
}
}
显示结果:
6.1 细节问题
- 当一个类中仅有一个带参数的构造方法是,参数类型会自动从Spring容器中获取
即:上述使用@Autowired+构造方法的形式不使用@Autowired也是可以的 - 当有多个构造方法时,Spring容器会优先使用无参的构造方法,如果还想要进行自动注入,需要在想注入的构造方法上使用@Autowired
- 当有多个构造方法时,@Autowired注解只能标注在一个构造方法上
- 当容器中不存在想要注入的Bean时也会报错,也就是说想要自动注入的Bean肯定是已经被Spring管理了的
- 设定@Autowired(requeired = false),如果想要自动注入的Bean在Spring容器中不存在可以设定默认值为空,如果存在则使用容器中的Bean
- 如果想要自动注入的Bean在Spring容器中存在多于一个可能会报Bean不唯一的错误,并且想要注入的Bean在本类中存在的变量名与Spring容器中该Bean的name属性一致,也会影响Bean的注入
- 如果想要自动注入的Bean在Spring容器中存在多于一个,又想指定想要注入的Bean,则在该Bean上加注解@Primary或者在Spring配置的bean标签内加primary属性为true
- 如果不想修改配置和Bean,只想在变量声明上注释也是可以的,增加@Autowired+@Qualifier注解
@Qualifier("想要注入的Bean的配置名称")
或者直接使用@Resource(name="想要注入的Bean的配置名称")