Spring--官方文档部分翻译(第一章)

https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html

1.4 依赖

1.4.1 依赖注入(DI)

  • DI是这样一个过程,对象仅通过(构造方法参数、工厂方法参数从工厂方法构造或返回对象实例化后设置的属性)来定义它们的依赖项。容易在生成bean之后注入这些依赖。这个过程将之前的流程反转了–即bean通过直接构造类来自行控制实例化或定位依赖。
  • DI使代码更为简洁,对象只提供它们的依赖,但不需要寻找依赖的位置(这些管理和寻找都由容器做好了)。
    (1)基于构造器的依赖注入
public class SimpleMovieLister {
    // the SimpleMovieLister has a dependency on a MovieFinder
    private MovieFinder movieFinder;
    // a constructor so that the Spring container can inject a MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // business logic that actually uses the injected MovieFinder is omitted...
}

(2)基于setter的依赖注入

  • 循环依赖:beanA构造器参数依赖beanB,同时beanB也依赖A,IOC容器抛出BeanCurrentlyInCreationException-----一种解决方式是使用setter注入提到构造器注入
  • spring会尽可能迟的设置属性和解析依赖,直到bean正在生成完成。因此spring可能加载成功,但真正请求bean时则抛出错误(比如bean缺少属性)。
  • 如果没有循环依赖,多个组合bean会注入一个独立的bean,其中的每个组合bean在次注入之前都会完成配置。比如说,A依赖B,当B作用A之前会先自行配置完成。

1.4.2 依赖和配置的细节

  • 如果A依赖B,那么B相当于A的一个属性。通xml的“depends-on”配置

1.4.3 懒加载(Lazy-initialized)

  • 默认情况下,在初始化过程中,ApplicationContext的实现类会积极积加载所有的单例类。通常这种预先实例化是需要的,因为配置和环境的错误会立即发现,而不用等很久之后。如果不想这么做,可以将bean标记为”lazy-initialized“来阻止单例类的预先实例化。
  • 但如果正常bean依赖于懒加载bean时,ApplicationContext也会执行预先实例化。
<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>

1.4.5 Autowiring Collaborators

1.4.6 方法注入

  • 通常情况下容器里都是单例bean。当单例bean与非单例bean组合成非单例bean时,需要显式控制依赖,通过将一个bean定义为另一个bean的熟悉。

1.5 bean模式

1.5.1 单例模式(Singleton)

  • spring容器中bean默认模式。容器中只会有一个bean实例(对所有的请求、依赖都一样);用于无状态的bean;spring容器完全管理单例bean的生命周期(默认是在关闭容器时销毁bean,可以自定义销毁逻辑)

1.5.2 Prototype模式

  • 每次对该bean的请求都会创建一个新实例,用于有交互状态的bean
  • spring不会完全管理Prototype模式bean的生命周期,一旦创建就由client负责,需要client负责资源清理(或者JVM内存回收)。
  • 类似于Java中的new关键字,只创建,需要自己决定销毁。

1.5.3 单例与Prototype模式bean的依赖

  • 对于一个依赖PrototypeBean的单例bean,容器会先实例化一个组合PrototypeBean,然后再用PrototypeBean注入到另一个单例Bean,这个单例Bean才对外。

1.6 定制化bean的特性

1.6.1 Bean生命周期

控制生命周期的按照方式

  • InitializingBean 和 DisposableBean回调接口
  • 自定义init() and destroy() 方法
  • @PostConstruct and @PreDestroy 注解
    初始化执行次序:
    @PostConstruct—InitializingBean接口的afterPropertiesSet()方法–(BeanPostProcessor的回调方法)–自定义init方法(…)@PreDestroy—DisposableBean接口的destroy方法—自定义destroy方法
  • 不建议使用InitializingBean接口,建议使用@Bean中的“initMethod”属性
  • 不建议使用DisposableBean接口,建议使用@Bean中的“destroyMethod”属性

1.8.1 通过BeanPostProcessor自定义Bean

  • 如果想在Spring容器完成实例化和bean初始化后实现自定义逻辑,可以实现BeanPostProcessor的回调方法
  • Spring容器实例化bean,BeanPostProcessor使bean开始工作

1.8.2 通过BeanFactoryPostProcessor自定义配置元数据

1.8.3 通过FactoryBean自定义实例化逻辑

1.9 基于注解的容器配置

注解是否优于xml配置?

  • 各有优劣,取决于具体情况
  • 注解实现更为简洁和精准
  • xml可以免编译执行,同时依赖注入更集中化,在一些场合更适合
  • 两者同时出现时,xml会覆盖注解(注解先生效,xml在后面生效会覆盖注解)

1.9.1 @Required

1.9.2 @Autowired

1.9.3 @Primary

1.9.4 @Qualifier

1.9.6 CustomAutowireConfigurer

  • 是一种BeanFactoryPostProcessor,可以注册自定义的qualifier注解类型

1.9.7 @Resource(JDK5、6中使用较多)

1.9.8 @PostConstruct and @PreDestroy

1.10 Classpath扫描和组件管理

1.10.1 @Component等

  • @Component是普通的spring组织的注解,@Repository, @Service, and @Controller是特定应用场景下对@Component的专业化实现。

1.10.2 组合注解

  • @RestController相当于@Controller and @ResponseBody的组合

1.10.3 自动类探测,注册bean

  • 使用@ComponentScan 修饰@Configuration类,其中的basePackages属性为类所在的父package
  • 使用@ComponentScan时,AutowiredAnnotationBeanPostProcessor会被默认调用(???)。
@ComponentScan(basePackages = "org.example")
@ComponentScan("org.example")

1.10.4 使用Filters来自定义扫描

  • 设置:useDefaultFilters选项
@Configuration
@ComponentScan(basePackages = "org.example",
        includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
        excludeFilters = @Filter(Repository.class))
public class AppConfig {
    ...
}

1.10.5 在Component中定义Bean元数据(待深化)

  • 使用@Bean注解修饰方法
  • @Bean可修饰静态方法,使得他们被调用时不会再生成所包含的配置(为了安全起见)
  • 静态@Bean方法的调用不会被Spring容器所拦截,这是由于CGLIB中子类只能覆盖非static类
  • As a consequence, a direct call to another @Bean method has standard Java semantics, resulting in an independent instance being returned straight from the factory method itself.
  • 通常情况下,@Bean修饰的方法不能声明为private以及final,因为他们需要是可覆盖的。

1.10.6 命名可自探测的Component

  • 这类Component通过BeanNameGenerator生成,可以自定义该接口的实现

1.11 使用JSR 330注解

1.11.1 @Inject and @Named

  • 可以实现@Autowired功能,默认byType注入
  • 如果需要nyName注入,则使用@Name

1.15 ApplicationContext的额外功能

1.15.1 使用MessageSource实现跨语言

1.15.2 标准化好自定义事件

  • 通过ApplicationEvent类和ApplicationListener接口可以实现ApplicationContext的事件处理。如果一个context中的bean实现了ApplicationListener接口,那么每次向ApplicationContext发布ApplicationEvent,这个bean总会感知到。这是标准的“观察者”模式
  • 在spring-4.2之后,这种事件架构被极大改进了,可以通过注解实现而不是随意的发布event(也就是说,一个对象不在必须继承自ApplicationEvent)。一旦该对象被发布,我们会抓取它,并把它作为一个事件发给用户。
  • 用户也可以实现和发布自定义事件。
    基于注解的事件Listeners
public class BlackListNotifier {
    private String notificationAddress;
    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }
    @EventListener({BlackListEvent.class})
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
    }
}
  • 也可以支持通过SpEL语句定义的condition属性
@EventListener(condition = "#blEvent.content == 'my-event'")
public void processBlackListEvent(BlackListEvent blEvent) {
    // notify appropriate parties via notificationAddress...
}
  • 如果需要通过另一事件的处理结果来发送事件,可以改变方法,返回将要发布的事件。
@EventListener
public ListUpdateEvent handleBlackListEvent(BlackListEvent event) {
    // notify appropriate parties via notificationAddress and
    // then publish a ListUpdateEvent...
}
  • 这个方法在处理每一个BlackListEvent时,都会发布一个新的ListUpdateEvent。

异步Listener

  • 如果需要listener异步处理事件,可以使用@Async注解
@EventListener
@Async
public void processBlackListEvent(BlackListEvent event) {
    // BlackListEvent is processed in a separate thread
}

有序Listener

@EventListener
@Order(42)
public void processBlackListEvent(BlackListEvent event) {
    // notify appropriate parties via notificationAddress...
}

泛型事件

  • 使用同一个Event处理不同的事件对象
@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
    ...
}
public class EntityCreatedEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {

    public EntityCreatedEvent(T entity) {
        super(entity);
    }

    @Override
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getSource()));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值