基本概念
IOC概念
原先在代码中通过硬编码的方式来进行类的实例化,以及定义各个对象之间的依赖关系。现在将类的实例化操作以及对象之间的依赖关系交给Spring容器来管理。实际上控制器交给容器管理了,所以称之为IOC。Spring通过配置文件或者注解的方式来实现类的实例化,绑定关系等等。
控制bean的创建顺序
depend-on(xml) 或者 @DependsOn(annotation)
控制bean的懒加载
lazy-init=”true”(xml) 或者 @Lazy(annotation)
bean的scope类型
singleton 单例,整个容器中只会创建一个对象实例
prototype 原型,每次获取bean时都会创建一个新的对象
request 单个HTTP request请求中只会创建一个对象实例
session 单个HTTP session周期中只会创建一个对象实例
application 整个ServletContext周期内只有一个
websocket 整个websocket连接中中只有一个
aop:scoped-proxy用途
短作用域实例注入到长作用域实例中需要用到代理,因为长作用域的周期很长,例如scope为singleton的对象A,整个容器中初始化一次,它如果引用了一个短作用域的对象B(例如scope为request),就不能保证A是唯一的了,所以通过代理的方式来保证A不变,B的变化会通过代理对象对A隐藏掉。
<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.something.UserPreferences" scope="session">
<!-- instructs the container to proxy the surrounding bean -->
<aop:scoped-proxy/>
</bean>
<!-- a singleton-scoped bean injected with a proxy to the above bean -->
<bean id="userService" class="com.something.SimpleUserService">
<!-- a reference to the proxied userPreferences bean -->
<property name="userPreferences" ref="userPreferences"/>
</bean>
spring-context-indexer 提高项目启动速度(spring5)
用法
- 在项目中添加依赖包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>5.1.4.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
打包
在jar包中会生成 spring.components 索引文件,如下
#
#Tue Jan 22 22:03:24 CST 2019
spring.core.learning.aware.ContextFrefreshedEventListener=org.springframework.stereotype.Component
spring.core.learning.aware.ClassLoaderAware=org.springframework.stereotype.Component
spring.core.learning.aware.ConsoleLoggingNotificationListener=org.springframework.stereotype.Component
spring.core.learning.aware.Listener=org.springframework.stereotype.Component
spring.core.learning.transaction.AccountService=org.springframework.stereotype.Component
spring.core.learning.aware.NotifyService=org.springframework.stereotype.Component
开发生产等环境隔离
@Configuration
public class ProfileConfig {
@Bean("env")
@Profile("dev")
public Env devEnv() {
return new Env("dev");
}
@Bean("prod")
@Profile("prod")
public Env productEnv() {
return new Env("prod");
}
@Data
@AllArgsConstructor
public static class Env {
String name;
}
}
事件通知
用法
自定义事件类 extends
ApplicationEvent
订阅者实现
ApplicationListener<T>
接口, T可以传递自定义的事件类发布者实现
ApplicationEventPublisherAware
,通过ApplicationEventPublisher
进行事件下发
示例
//事件
@Data
public class Notify extends ApplicationEvent {
private String title;
private String content;
public Notify(Object source) {
super(source);
}
}
//生产者
public class NotifyService implements ApplicationEventPublisherAware {
private ApplicationEventPublisher eventPublisherAware;
public void notify(Notify notify) {
log.info("publish notify event: {}", notify);
this.eventPublisherAware.publishEvent(notify);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisherAware = applicationEventPublisher;
}
}
//订阅者,或者用@EventListener注解
@Service
public class Listener implements ApplicationListener<Notify> {
@Override
public void onApplicationEvent(Notify event) {
System.out.println("receive message: " + event.getTitle() + ", content:" + event.getContent());
}
}
#常见问题
###循环依赖
循环依赖主要是产生的原因通过构造函数来实现DI注入时,被注入的对象同时需要注入本对象。例如以下配置,解决办法是尽量使用setter方式注入,来替代构造函数注入的方式。
`
xml
<bean id="hefang" class="spring.core.learning.model.Student" name="hah">
<property name="className" value="701"/>
<property name="name" value="hefang"/>
<property name="teacher" ref="wanglaoshi"/>
</bean>
`