IOC
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)
spring实现IOC的思路和方法
spring实现IOC的思路是提供一些配置信息用来描述类之间的依赖关系,然后由容器去解析这些配置信息,继而维护好对象之间的依赖关系。
spring实现IOC的思路大致可以拆分成:
1 | 应用程序中提供类和类的依赖关系(属性或者构造方法) |
配置这些信息的方法有三种分别是xml,annotation和javaconfig,容器维护这些类和对象的过程称为自动注入,自动注入的方法有两种:构造方法和setter注入。
1 | schemal-based-------xml |
spring注入详细配置(字符串、数组等)参考文档:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-properties-detailed
Constructor-based Dependency Injection
1 | package x.y; |
1 | <beans> |
Setter-based Dependency Injection
1 | public class ExampleBean { |
1 | <bean id="exampleBean" class="examples.ExampleBean"> |
自动装配
IOC的注入需要提供的依赖关系,一是类的定义体现依赖关系,二是在配置文件中描述依赖关系。自动装配则把配置文件中描述依赖关系取消了,只要提供好类的依赖关系就可以把对象交给容器管理完成注入。
在实际开发中,描述类之间的依赖关系通常是大篇幅的,如果使用自动装配则省去了很多配置,并且如果对象的依赖发生更新我们可以不需要去更新配置,但是也带来了一定的缺点。
自动装配的方法有四种:no/byName/byType/constructor
从自动装配中排除Bean
在每个bean的基础上,您可以从自动装配中排除一个bean。使用Spring的XML格式,将元素的autowire-candidate属性设置
懒加载
1 | <bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/> |
或注解形式@Lazy
Spring Bean的作用域
xml方式
1 | <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/> |
或者直接使用注解方式。
Spring的方法注入可分为两种
查找方法注入:用于注入方法返回结果,也就是说能通过配置方式替换方法返回结果。即我们通常所说的lookup-method注入。
1 | 单例模式的bean只会被创建一次,IoC容器会缓存该bean实例以供下次使用;原型模式的bean每次都会创建一个全新的bean,IoC容器不会缓存该bean的实例。 |
替换方法注入:可以实现方法主体或返回结果的替换,即我们通常所说的replaced-method注入。
lookup-method注入 @Lookup
** 在Singleton 当中引用了一个Prototype的bean的时候引发的问题: **
1 | 在Spring的诸多应用场景中bean都是单例形式,当一个单利bean需要和一个非单利bean组合使用或者一个非单利bean和另一个非单利bean组合使用时,我们通常都是将依赖以属性的方式放到bean中来引用,然后以@Autowired来标记需要注入的属性。 |
解决方式:去找 或者赋值
1、Method Injection
继承ApplicationContextAware 每次调用方法时用上下文的getBean(name,class)方法去重新获取bean B的实例。
1 | package fiona.apple; |
2、Lookup Method Injection
1 | public abstract class CommandManager { |
通过一个注解或xml配置实现
1 | <!-- a stateful bean deployed as a prototype (non-singleton) --> |
1 | public abstract class CommandManager { |
replaced-method注入
主要作用就是替换方法体及其返回值,其实现也比较简单
replace-method注入需实现MethodReplacer接口,并重写reimplement方法。
Lifecycle Callbacks 生命周期回调
初始化回调
实现接口org.springframework.beans.factory.InitializingBean 指定一个方法: void afterPropertiesSet() throws Exception;
或者是配置文件中直接一个初始化方法:
1 | <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> |
销毁回调
org.springframework.beans.factory.DisposableBean当包含该接口的容器被销毁时,实现该接口可使Bean获得回调 public void destroy() 。
1 | <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/> |
注解方式实现:从Spring 2.5开始,可以使用三种方式来控制Bean生命周期行为:
1、在InitializingBean(初始化bean之后)和 DisposableBean回调接口
2、配置init()和destroy()方法
3、在@PostConstruct(初始化bean之前)和@PreDestroy 注释。您可以结合使用这些机制来控制给定的bean。
如果同一个bean配置的具有不同初始化方法的顺序为:
1 | 用注释的方法 @PostConstruct |
相关注解
1 | @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常 |
depends-on
如果 bean 是另一个的依赖关系,则需要首先注入这个类。
1 | <bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"> |
生成候选组件的索引
当有很多个类需要扫描,会比较慢,使用如下包来在编译的时候就加入到索引,按照索引的方式去扫描就会很快。
1 | <dependencies> |
java也有一套注解,可以用来开发spring。