spring 复习整理二

微信截图_20220426220935

spring 复习整理二(仗剑走天涯)

Bean的作用域

scope 描述
singleto 每个bean在ioc容器中都是独一无二的单例形式
prototype 将单个beanDifination定义为,spring容器可以【实例化任意数量】的对象实例
request 将单个beanDifination限定为单个HTTP请求的生命周期。 也就是说,每个HTTP请求都有自己的bean实例,它是在单个beanDifination的后面创建的。 仅在web环境中的Spring【ApplicationContext】的上下文中有效
session 将单个beanDifination定义为HTTP 【Session】的生命周期。 仅在web环境中的Spring 【ApplicationContext】的上下文中有效
application 将单个beanDifination定义为【ServletContext】的生命周期。 仅在web环境中的Spring 【ApplicationContext】的上下文中有效
websocket 将单个beanDifination作用域定义为【WebSocket】的生命周期。 仅在web环境中的Spring【ApplicationContext】的上下文中有效

生命周期回调

初始化

  • 接口形式(不建议使用)

org.springframework.beans.factory.InitializingBean.InitializingBean的接口允许bean在容器设置了bean上的所有必要属性之后执行【初始化工作】。【InitializingBean】接口指定了一个方法 这种接口形式将你的代码与Spring的代码耦合在一起 所以不建议使用

1
void afterPropertiesSet() throws Exception;
  • xml配置
1
2
<bean name="a" class="com.dream.xiaobo.entity.A"
autowire="byType" init-method="init" />

init-method="init":为这个Bean的init方法设置为初始化功能

  • 注解形式
    jdk8自带@PostConstruct

jdk8以上 引入依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

注意 在spring中要想使用注解需要先开启注解功能 在Bean中引入相应的规范文档

1
2
3
4
xmlns:p="http://www.springframework.org/schema/p"

http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
1
2
<!--    开启spring注解 自动装载到容器当中 需要引入命名空间以及规范文档-->
<context:annotation-config />
1
2
3
4
@PostConstruct
public void init(){
System.out.println("init");
}

销毁

  • 接口形式

实现org.springframework.beans.factory.DisposableBean接口可以让bean在管理它的容器被销毁时获得回调。 ‘ DisposableBean ‘接口指定了一个方法

1
void destroy() throws Exception;
  • xml形式
1
2
<bean name="a" class="com.dream.xiaobo.entity.A"
autowire="byType" destroy-method="destroy"/>

destroy-method="destroy":为这个Bean的destroy方法设置销毁功能

  • 注解形式
1
2
3
4
@PreDestroy
public void destroy(){
System.out.println("destroy");
}

默认初始化和销毁方法

1
<beans default-init-method="init"></beans>

规定方法名为init和destory

ApplicationContextAware 和 BeanNameAware

  • ApplicationContextAware
1
2
3
4
5
public interface ApplicationContextAware extends Aware {

void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}
  • BeanNameAware
1
2
3
4
5
public interface BeanNameAware extends Aware {

void setBeanName(String name);

}

Other Aware Interfaces

命名 依赖注入
ApplicationContextAware 将ApplicationContext注入bean当中
ApplicationEventPublisherAware 将ApplicationEventPublisherAware注入bean当中
BeanClassLoaderAware 将类加载器用于装入bean类
BeanFactoryAware 将BeanFactory注入bean当中
BeanNameAware 将bean的名称注入bean中
ResourceLoaderAware 配置了用于访问资源的加载器
ServletConfigAware 当前的’ ServletConfig ‘容器运行。 仅在web感知的Spring ‘ ApplicationContext ‘中有效
ServletContextAware 当前运行容器的“ServletContext”。 仅在web感知的Spring ‘ ApplicationContext ‘中有效

基于注解的容器配置

@Autowired

自动装配,有byType的语义

@Autowired使用场所

可以将@Autowired注解应用到传统的 setter方法

可以将注解应用到具有任意名称和多个参数的方法

可以将 @Autowired 应用到字段上(常用),甚至可以将它与构造函数混合使用

可以将 @Autowired 应用到数组、list、set集合上

可以将@Autowired 应用到Map集合上 只要期望的键类型是“String”,也可以自动连接。 映射值包含预期类型的所有bean,键包含相应的bean名

注意

默认情况下,当给定注入点没有可用的匹配候选bean时,自动装配将失败。 对于声明的数组、集合或映射,至少需要一个匹配元素

通过将@Autowired中的 required 属性设置为 false 来让框架跳过它

@Primary

@Primary表示当多个bean可以作为一个依赖项的候选bean时,应该优先考虑某个特定bean。 如果在候选bean中恰好存在一个主要的bean,那么它将成为自动连接的值

@Qualifier

通过使用 @Qualifier 注解,我们可以消除需要注入哪个 bean 的问题

@Resouse

JSR-250的 【@Resource】注解(‘ javax.annotation.Resource ‘)来支持注入

@Resource 带有一个name属性 默认情况下,Spring将该值解释为要注入的bean名 换句话说,它遵循by-name语义

如果没有显式指定名称,则默认名称为【字段名或setter方法的参数名】。 对于字段,它接受字段名。 对于setter方法,它采用bean属性名

先根据by-name进行注入 如果根据by-name没有找到 会根据by-type继续注入

ClassPath扫描

xml方式扫描

XML来指定配置元数据 这些元数据在Spring容器启动时被扫描,每一个bean的元数据对应生成一个“BeanDefinition”

前面介绍到的都是这种xml方式的扫描

注解方式扫描

使用注解 通过扫描筛选并在容器中注册了相应beanDifination的类。 这样就不需要使用XML来执行bean注册

1
2
3
@Controller
public class OrderController {
}
1
2
3
@Service
public class OrderService {
}
1
2
3
@Repository
public class OrderDao {
}
1
2
3
4
@Configuration
@ComponentScan(value = "com.dream.xiaobo")
public class AppConfig {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">


<!-- 开启扫描 开启scan 也 意味着开启了annotation-config -->
<context:component-scan base-package="com.dream.xiaobo" />

</beans>

context:component-scan 的使用会隐式启用 context:annotation-config,当使用 context:component-scan时,通常不需要包含context:annotation-config元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void TestIoc(){

AnnotationConfigApplicationContext appConfig = new AnnotationConfigApplicationContext(AppConfig.class);

OrderService bean = appConfig.getBean(OrderService.class);
LOGGER.info("{}",bean);

ApplicationContext context = new ClassPathXmlApplicationContext("scan.xml");

OrderService orderService = context.getBean(OrderService.class);

LOGGER.info("{}",orderService);
}

@Component 是任何spring管理组件的通用注解

@Repository@Service@Controller@Component 用于更具体用例的注解(分别在持久性、服务和表示层中)。这些注解对于我们对特定bean进行批量处理时是有帮助的

@Configuration 可以理解为等同于xml配置

ComponentScan 要扫描的包

组件命名

当组件作为扫描过程的一部分被自动检测时,它的bean名是由该扫描器所知道的“BeanNameGenerator”策略生成的

自动检测组件提供scope

与spring管理的组件一样,自动检测组件的默认和最常见的作用域是“单例”。 然而,有时您需要一个不同的范围,可以由’ @Scope ‘注解指定

1
2
3
4
5
@Scope("prototype")
@Repository
public class Test(){

}

使用过滤器自定义扫描

默认情况下,带有@Component、@Repository、@Service、@Controller、@Configuration注解的类是一定能被筛选器选中并进行注册的候选组件。 但是,您可以通过应用自定义过滤器来修改和扩展此行为,自由定制筛选哪些或不包含那些组件。 将它们作为@ComponentScan注解的includeFilters 或 excludeFilters 属性添加 每个筛选器元素都需要’ type ‘和’ expression ‘属性

过滤方式 示例表达式 描述
annotation (默认) org.example.SomeAnnotation 要在目标组件的类型级别上“存在”或“元注解存在”的注解
assignable org.example.SomeClass 指定要排除的bean的类
aspectj org.example..*Service+ 要被目标组件匹配的AspectJ类型表达式
regex org.example.Default.* 由目标组件的类名匹配的正则表达式
custom org.example.MyTypeFilter org.springframework.core.type的自定义实现,TypeFilter”接口
  • 注解形式
1
2
3
4
5
6
7
@Configuration()
@ComponentScan(basePackages = "com.dream.xiaobo",
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION),
excludeFilters = @ComponentScan.Filter(Repository.class)
)
public class AppConfig {
}
  • xml形式
1
2
3
4
<context:component-scan base-package="com.dream.xiaobo">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

@Bean和@Configuration

@Bean注解用于指示一个方法,该方法负责 实例化、配置和初始化 一个由Spring IoC容器管理的新对象

@Configuration注解的一个类表明它的主要目的是作为beanDifination的源,我们通常称之为 配置类。 此外,@Configuration 类允许通过调用同一类中的其他 @Bean 方法来 定义bean间的依赖关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class MyConfiguration {

@Bean
@Qualifier(value = "orders")
public Orders orders(){
return new Orders();
}

@Bean
public User user(@Qualifier("orders") Orders orders){

User user = new User();

user.setOrders(orders);

return user;
}
}
1
2
3
4
5
6
7
8
9
10
@Test
public void TestIoc(){


AnnotationConfigApplicationContext appConfig = new AnnotationConfigApplicationContext(AppConfig.class);

MyConfiguration bean = appConfig.getBean(MyConfiguration.class);

LOGGER.info("{}",bean.user(bean.orders()));
}

生命周期回调

如果一个bean实现了’ InitializingBean ‘、’ DisposableBean ‘或’ Lifecycle ‘,则容器会调用它们各自的方法

@Bean注解支持指定任意的初始化和销毁回调方法,就像Spring XML在’ bean ‘元素上的’ init-method ‘和’ destroy-method ‘属性一样

指定Bean的范围

Spring包含了【@Scope】注解,可以指定bean的范围

默认的作用域是 singleton ,可以用 @Scope 注解来覆盖它

Bean别名

1
@Bean({"dataSource", "A-dataSource", "B-dataSource"})

Bean描述

1
@Description("Provides a basic example of a bean")

@Configuration

@Configuration 是一个类级注解,指示一个对象是beanDifination的源。@Configuration类通过@Bean带注解的方法声明bean

当@Bean方法在没有标注@Configuration的类中声明时,它们被认为是在【lite】模式下处理的。 在【@Component】中声明的Bean方法甚至在一个普通的类中声明的Bean方法都被认为是【lite】。在这样的场景中,【@Bean】方法是一种通用工厂方法机制。

与@Configuration 不同,【lite】模式下 【@Bean】方法不能【声明bean】间的【依赖关系】。 因此,这样的【@Bean】方法不应该调用其他【@Bean】下的方法。 每个这样的方法实际上只是特定bean引用的工厂方法,没有任何特殊的运行时语义。

在一般情况下,@Bean方法要在【@Configuration】类中声明,这种功能情况下,会使用【full】模式,因此交叉方法引用会被重定向到容器的生命周期管理。 这可以防止通过常规Java调用意外调用相同的Bean,这有助于减少在【lite】模式下操作时难以跟踪的微妙错误

@import

引用另一个配置类

1
2
3
4
5
6
7
8
@Configuration
public class ConfigImportA {

@Bean
public ImportA testImport(){
return new ImportA();
}
}
1
2
3
4
5
6
7
8
9
10
@Configuration
@Import(ConfigImportA.class)
public class configImportB {
@Bean
public configImportB testImport(){

return new configImportB();
}

}

java结合xml

1
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>

context:property-placeholder:引入配置文件

BeanFactory和FactoryBean

BeanFactory

Bean工厂 负责管理我们的Bean 通过他我们可以从容器中去检索Bean

FactoryBean

工厂Bean 可以创建复杂对象 他拥有三个方法

1
2
3
4
5
6
7
8
9
 @Nullable
T getObject() throws Exception;

@Nullable
Class<?> getObjectType();

default boolean isSingleton() {
return true;
}

getobject 拿到对应的类

getObjectType 拿到对应类的类型

isSingleton 判断是否为单例

环境抽象

接口是一个抽象,集成在容器中,它模拟了应用程序环境的两个关键方面:profiles and properties

profiles

Profiles在核心容器中提供了一种机制,允许在不同环境中注册不同的Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
@ComponentScan("com.dream.xiaobo")
public class DataSourceConfig {

@Bean
@Profile("prod")
public DataSource proDataSource(){

System.out.println("生产环境");
return new ProDatabase();
}

@Bean
@Profile("dev")
public DataSource devDataSource(){
System.out.println("开发环境");
return new DevDatasource();
}

}
1
2
3
public class DevDatasource implements DataSource {
//此处为实现的方法
}
1
2
3
public class ProDatabase implements DataSource {
//此处为实现的方法
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void TestIoc(){

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

// 激活环境
applicationContext.getEnvironment().setActiveProfiles("prod");

// 扫包
applicationContext.scan("com.dream.xiaobo");

// 刷新
applicationContext.refresh();

// 使用
DataSource bean = applicationContext.getBean(DataSource.class);

LOGGER.info("{}", bean);

虚拟机参数方式

1
-Dspring.profiles.active=dev

编程式

1
applicationContext.getEnvironment().setActiveProfiles("prod");

properties

Spring的【环境抽象】提供了对【属性】的搜索操作

编程对象式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyPropertySource extends PropertySource {

private Properties properties = new Properties();

public MyPropertySource(String name) {
super(name);
properties.put("xiaobo","properties");
}

@Override
public Object getProperty(String s) {

return properties.get(s);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void TestIoc(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();


ConfigurableEnvironment environment = applicationContext.getEnvironment();

MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(new MyPropertySource("my"));

applicationContext.refresh();

String xiaobo = environment.getProperty("xiaobo");

LOGGER.info(xiaobo);
}

@PropertySource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@PropertySource("classpath:myconfig.properties")
public class AConfig {

@Value("${path}")
private String path;

@Override
public String toString() {
return "A{" +
"path='" + path + '\'' +
'}';
}
}
1
2
3
4
5
6
7
8
9
@Test
public void TestIoc(){

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AConfig.class);

AConfig bean = applicationContext.getBean(AConfig.class);

LOGGER.info("{}",bean);
}

你知道的越多 你不知道的越多 嘿 我是小博 带你一起看我目之所及的世界……

-------------本文结束 感谢您的阅读-------------

本文标题:spring 复习整理二

文章作者:小博

发布时间:2022年04月26日 - 22:12

最后更新:2022年04月26日 - 22:13

原始链接:https://codexiaobo.github.io/posts/2916426880/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。