1 概览总结
1.1 核心实现包:
-
org.springframework.beans
-
org.springframework.context
1.2 核心对象:
-
BeanFactory
-
ApplicationContext
2 容器
Spring 容器里面的对象,都称之为Bean,同一由容器创建、分配、管理。
可以通过创建`ClassPathXmlApplicationContext` 或
FileSystemXmlApplicationContext
来创建容器。提供一些xml配置信息。不常用,在
测试中看到使用过,创建容器,获取bean对象。
2.1 元信息
元信息,用于创建bean对象。元信息可以通过三种方式定义:
-
xml 最原始的方式,所有bean均可通过xml定义
-
注解:例如@Service @Component,这些注解的类,会被创建bean对象
-
java 配置。可以再java类中进行bean对象,配置。结合 @Configuration, @Bean,等等对象。
2.2 创建容器
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
xml均为需要配置的对象文件。应用场景不广,不做深入研究。
2.3 使用容器
容器,实质就是bean对象的一个集合,可以从容器中获取想要的bean对象,bean默认是单例。
// 创建容器
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
// 获取对象
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// 使用对象方法
List<String> userList = service.getUsernameList();
2.4 Bean 对象
2.4.1 bean 命名
bean 对象可以有多个名称,但是必须全局唯一。可以通过xml通过id或者name属性设置。注解也可设置name属性,如果不设置,默认类名小写开头,驼峰。accountManager, accountService, userDao, loginController 等等。
可以设置别名,等效,但是一般没用到过。
2.5 初始化 bean 的多种方式
看了一遍,没啥感觉。
3 依赖
构造器注入,以及set注入,结合xml中属性进行对象配置。不太实用了。现在都是注解。
4 bean 的scopes
-
singleton 在IOC容器中只存在一个实例,也就是通过singleton作用域创建的对象是单例的。
-
prototype 第次从IOC容器中获取对象时,都返回一个新对象。
-
request 每次HTTP请求都会创建一个新的对象,当请求结束时则会自动销毁这个对象。该作用域只针对Web环境中使用。
-
session 同一个HTTP Session共享一个对象,不同的HTTP Session使用不同的对象,当这个Session结束时销毁这个对象。该作用域也是只针对Web环境中使用的。
-
globalSession 同一个全局Session共享一个对象,该作用域也是只针对Web环境中使用的。
注:还可以自定义作用范围。
5 自定义 bean nature
-
bean 生命周期,各种回调。
-
ApplicationContextAware and BeanNameAware
-
其他 Aware 接口
5.1 生命周期回调
方式: - 实现 InitializingBean 、DisposableBean ,实现方法,从而实现bean初始化、销毁时回调函数。 - 使用JSRO-250 @PostConstruct @PreDestroy 注解,在bean对象创建前,销毁后执行。
5.1.1 初始化回调
-
实现 InitializingBean ,并实现 afterPropertiesSet 方法,即可
-
使用注解 @PostConstruct 标注初始化方法。
-
使用 init-method 属性(xml中), initMethod 属性(@Bean)
5.1.2 销毁时回调
-
实现 DisposableBean 接口
-
使用 @PreDestroy 标注方法
-
使用 destroy-method 属性(xml中), destroyMethod 属性(@Bean)
5.2 启动 和 关闭 回调
有些特殊场景,一些对象有自己独特的生命周期需要,可以设置启动或者关闭时回调。核心接口
Lifecycle
。
5.3 非web应用,关闭 IOC 容器时回调
5.4 Aware
感知、意识到。使用Aware,将与Spring耦合。 https://my.oschina.net/u/4149877/blog/3076044
6 Bean 定义继承
Bean,如果继承父类,父类bean的属性可以被子类bean继承。
7 容器扩展方法
忽略
8 基于注解的容器配置
8.1 @Required
Spring 5.1 开始弃用此注解。此注解作用为,标注在配置期间,bean的属性必须存在。严格意义上检查,避免空指针。
8.2 @Autowired
JSR 330 @Inject 作用相同。
-
作用于构造器上,注入对象
-
作用于 setter 上,注入对象
-
作用于 方法上,注入对象
-
作用于 对象上
-
可混合使用
此外还有一个注解 @Resource, 此注解也能注入对象,但是有局限性,只支持 filed 以及setter方法,且只能有一个参数。
非必须:注入对象时,不一定需要此对象存在。
-
@Autowired(required = false)
-
Optional
-
@Nullable
通过 @Order 或者 @Priority 注解,可以设置优先级。不使用注解,可以通过实现接口 org.springframework.core.Ordered
8.3 @Primary
注入对象的时候,默认是根据类型注入的,这时候可以指定优先级,则在注入的时候,优先注入级别高的。
8.4 @Qualifier
使用此注解, 可以指定注入命名的bean。在生成需要依赖的Bean对象时。
自定义 qualifier 注解。
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
然后就可以用 @Genre 代替 @Qualifier。
8.5 @Value
-
一般用于注入属性值
-
使用 EL 表达式,生成所需属性
9 classpath 扫描以及管理 components
9.1 常见注解
@Repository, @Component, @Service, and @Controller
根据业务功能选择合适的注解进行标注,如如controller层选用@Controller。尤其需要注意的是@Component,这个可以用来标识Bean,但非service层的。
9.2 元注解和组合注解
spring 提供的注解大多是元注解,可以组合其他注解,将功能进行结合。
例如 @RestController 包含@Controller and @ResponseBody,可以实现2个注解的作用。
@Scope(WebApplicationContext.SCOPE_SESSION)
@SessionScope
9.3 扫描
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
将 org.example
包下使用注解标注的Bean对象,创建、管理。
9.5 使用compoent 定义 Bean 的元信息
@Component
public class FactoryMethodComponent {
@Bean @Scope("prototype")
public TestBean prototypeInstance(InjectionPoint injectionPoint) {
return new TestBean("prototypeInstance for " + injectionPoint.getMember());
}
}
@Component 标注类。多个注解标注生成的Bean对象。
9.6 Bean 命名
在定义Bean时,可以手动指定名称,也可以不指定,使用默认的bean name 生成策略(类名首字母小写,驼峰)。当然也可以自定义。
实现 BeanNameGenerator 接口。生成Bean对象时,指明name生成策略
@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {
// ...
}
9.7 使用 scope 指定 自动检测 components
使用 @Scope,默认是 singleton, 可以通过注解指定范围。也可以自定义范围解析类。
实现 ScopeMetadataResolver
接口
指定范围解析。
@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
public class AppConfig {
// ...
}
还可以限制范围代理类型
@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {
// ...
}
scopedProxy: no, interfaces, and targetClass
10 使用 JSR 330 标准注解。
需要加入jar
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
其实就是spring 相关注解的另一种同等作用注解。
Spring | javax.inject.* | javax.inject restrictions / comments |
---|---|---|
@Autowired |
@Inject |
@Inject has no ‘required’ attribute. Can be used with Java 8’s Optional instead. |
@Component |
@Named / @ManagedBean |
JSR-330 does not provide a composable model, only a way to identify named components. |
@Scope(“singleton”) |
@Singleton |
The JSR-330 default scope is like Spring’s prototype. However, in order to keep it consistent with Spring’s general defaults, a JSR-330 bean declared in the Spring container is a singleton by default. In order to use a scope other than singleton, you should use Spring’s @Scope annotation. javax.inject also provides a @Scope annotation. Nevertheless, this one is only intended to be used for creating your own annotations. |
@Qualifier |
@Qualifier / @Named |
javax.inject.Qualifier is just a meta-annotation for building custom qualifiers. Concrete String qualifiers (like Spring’s @Qualifier with a value) can be associated through javax.inject.Named. |
@Value |
- |
no equivalent |
@Required |
- |
no equivalent |
@Lazy |
- |
no equivalent |
ObjectFactory |
Provider |
javax.inject.Provider is a direct alternative to Spring’s ObjectFactory, only with a shorter get() method name. It can also be used in combination with Spring’s @Autowired or with non-annotated constructors and setter methods. |
了解即可。还是使用spring。
11 基于java代码,进行容器配置
主要是关于 @Comfiguration 以及 @Bean
-
@Configuration 重量级选手,在其配置内,可以解决依赖问题。
-
@Bean 轻量级,结合component注解,也能生成bean对象,但是如果内部复杂,有其他依赖,则无法实现。只使用于简单的bean对象生成。
11.1 @Import
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
通过import,生成ConfigB中的Bean对象,也会同时生成ConfigA中的Bean、
11.2 环境设置
@Profile注解。 - @Profile(“development”) - @Profile(“production”)
development/production等均为自定义的环境变量值。可用于设置了某种环境下,执行对应的配置。
@PropertySource(“classpath:/com/myco/app.properties”)
指定属性源文件。
11.3 spring 中的事件机制
步骤: - 定义事件 - 发送事件 - 监听事件,也即处理事件。
11.3.1 定义事件
spring 内置了几类事件。
自定义事件
public class BlockedListEvent extends ApplicationEvent {
private final String address;
private final String content;
public BlockedListEvent(Object source, String address, String content) {
super(source);
this.address = address;
this.content = content;
}
// accessor and other methods...
}
11.3.2 发送事件
public class EmailService implements ApplicationEventPublisherAware {
private List<String> blockedList;
private ApplicationEventPublisher publisher;
public void setBlockedList(List<String> blockedList) {
this.blockedList = blockedList;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void sendEmail(String address, String content) {
if (blockedList.contains(address)) {
publisher.publishEvent(new BlockedListEvent(this, address, content));
return;
}
// send email...
}
}
ApplicationEventPublisher#publishEvent(),则可发送事件。
11.3.3 监听事件,处理事件
方式一:实现接口
public class BlockedListNotifier implements ApplicationListener<BlockedListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}
}
方式二:使用注解@EventListener
public class BlockedListNotifier {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
@EventListener
public void processBlockedListEvent(BlockedListEvent event) {
// notify appropriate parties via notificationAddress...
}
}
@EventListener,还可以有些属性,进行针对性监听。可结合@Async、@Order(42)使用