Spring IOC
IoC: Incerse of Control(控制反转)
控制反转是一种设计思想,就是将原本在程序中手动创建对象的控制权交由Spring框架来管理。也就是说,Spring将我们从盘根错节的依赖关系中解放了。当前对象如果需要依赖另一个对象,只要打一个@Autowired注解,Spring就会自动创建好对象放入到@Autowired标注的变量中。从而实现松耦合。
正控:若要使用某个对象,需要自己去负责对象的创建。
反控:若要使用某个对象,只需要从Spring中获取需要使用的对象,不关心对象的创建过程,也就是把对象的创建过程交给了Spring框架。
DI:Dependency Injection(依赖注入)
DI:Spring创建对象的过程中,讲对象依赖属性(常亮,对象,集合),通过配置设置值给该对象。
IoC核心Spring IOC容器(Container):
对于IOC来说最重要的是容器,容器管理者生命周期,控制着依赖注入。
Spring IOC容器主要基于以下两个接口:
BeanFactory:Spring最底层的接口,只提供了IoC的功能,负责创建、组装、管理Bean,在应用中一般不适用BeanFactory,而推荐使用
ApplicationContext(应用上下文)。
ApplicationContext接口继承了BeanFactory,除此之外还提供了AOP继承,国际化处理、事件处理、统一资源价值等功能。
Appliacation 是BeanFactory的子接口,即Beanfactory相对处于底层;而Applicaton是相对高级的接口。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,
HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
}
SpringIOC创建Bean:
bean创建的时机:
- a.BeanFactory需要等到获取某一个bean的时候会参与创建该bean----延迟实例化
- b.ApplicationContext在启动Spring容器时就会创建搜所有的Bean(WEB应用建议)。
- Bean实例化方式
- a.构造器实例化(无参构造器),最标准,使用最多。
- b.静态工厂方法实例化:解决系统系统遗留问题。
使用工厂的静态方法获取对象。public class SomeBean{ } public class SomeBeanFactory{ public static SomeBean createInstance(){ return new SomeBean(); } } //xml配置中: <bean id="someBean" class ="com.xxx.xxx.SomeBeanFactory" factory-method="createInstance"/>
- c.实例工厂方法实例化: 解决系统遗留问题。
与上一种方式不同在于先创建工厂对象再从工厂中获取对象。public class SomeBean{ } public class SomeBeanFactory{ public static SomeBean createInstance(){ return new SomeBean(); } } //xml配置中: <bean id="factory" class ="com.xxx.xxx.SomeBeanFactory" /> <bean id="someBean" factory-bean="factory" factory-method="createInstance"/>
- d.实现FactoryBean接口实例化,实例工厂变种。(如果集成MyBatis框架使用:org.mybatis.spring.SqlSessionFactoryBean)
public class SomeBean{ } public class SomeFactoryBean implements FactoryBean<SomeBean>{ public SomeBean getObject() throws Excetpin{ return new SomeBean(); } public Clall<?> getObjectType(){ return SomeBean.class; } } <bean id="someBean" class="包名.SomeBeanFactoryBean"/>
- Bean作用域
在Spring容器中是指其创建的Bean对象的Bean对象相对于其他Bean对象的请求可见范围,定义语法格式:
<bean id=" " class=" " scope="作用域"/>
| scope参数值 | 解释 |
|---|---|
| singleton | 单例,在SpringIOC中仅存在一个实例(默认的scope) |
| prototype | 多例,每次从容器中调用Bean时,都返回一个新的实例,不会再容器启动时创建对象 |
| request | 用于WEB开发,将Bean放入request范围,request.setAttribute("xxxx"),在同一个request获得同一个Bean |
| session | 用于web开发,将bean放入session范围,在同一个session获得同一个Bean |
| globalSession | 一般用于Porlet应用环境,分布式系统存在全局Session概念(单点登录),如果不是Prolet环境,相当于Session |
- Bean的初始化和销毁
Spring IoC容器可以帮我们管理对象的创建,也可以帮我们管理创建之后的初始化和回收之前的扫尾操作。
<bean id="someBean" class="..."
init=method="该类中初始化方法名"
destory-method="该类中销毁方法名">
</bean>
DI核心(依赖注入--注入Bean):
DI ----Dependency Injection, 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中。
即Ioc负责创建对象,DI用来把创建的对象赋值到需要Bean对象的变量中。
DI注入Bean:
- Setter方法注入:
其实就是通过对象的Setter方法来完成对象的设置操作:
- 使用Bean元素的子元素设置:
- 常量类型,直接使用value设置
- 引用类型,使用ref赋值
- 集合类型,直接使用对应的集合类型元素即可。
- Spring通过属性的Setter方法注入值
- 在配置文件中配置的值都是String,Spring可以自动完成类型的转化 属性的设置值是在init方法执行之前完成的。
注入常量值(简单类型): 语法:
<property name="对象属性名称">
<value>需要注入的值</value>
</property>
注入对象:
<property name="对象属性名称">
<ref bean="被注入对象的bean的id">
</property>
//简写
<property name="对象属性名称" ref="被注入对象的bean的id"/>
注入集合:
<property name="listElement">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<property name="arrayElement">
<array>
<value>array1</value>
<value>array2</value>
</array>
</property>
<property name="setElement">
<set>
<value>set1</value>
<value>set2</value>
</set>
</property>
<property name="mapElement">
<map>
<entry>
<key><value>map1</value></key>
<value>map1value</value>
</entry>
<entry>
<key><value>map2</value></key>
<value>map2value</value>
</entry>
</map>
</property>
<property name="propsElement">
<props>
<prop key="prop1">prop1</prop>
<prop key="porp2">prop2</prop>
</props>
</property>
- 构造器注入:
通过构造器,在完成创建对象的时候,同时初始化对象设置数据。
setter方式注入使用:<property/>元素
构造器方式注入使用:<constructor-arg/>元素
- 注入常量使用value,注入对象使用ref,注入集合使用对象的集合元素即可
- 默认情况下constructor-arg的顺序就是构造器参数的顺序(不建议)
- 调整构造器中参数顺序:
- index:构造求器参数位置,从0开始(不建议)
- type:构造器中参数类型。(不建议)
- name:构造器中按照构造器的参数名字设置值(建议)
<bean id="someBean" class="com.xxx.SomeBean">
<constructor-arg name=name",value="will"/>
<constructor-arg name="age",value="17"/>
<constructor-arg name="other" ref="otherBean"/>
<constructor-arg name="prop">
<value>
pkey1=pvalue1
pkey2=pvalue2
</value>
</constructor-arg>
</bean>
- 方法注入:
通过配置方式覆盖或拦截指定的方法,通常通过代理模式实现。
Spring提供两种方法注入:查找方法注入和方法替换注入
因为Spring通过CGLIB动态代理方式实现方法注入,也就是通过动态修改类型的字节码来实现,本质就是生成需方法注入的类的子类方式实现。
方法定义格式:必须保证子类被覆盖
- 查找方法的类和被重载的方法必须为final
- 访问级别必须是public 或 protected
- 可以使抽象方法,必须有返回值,必须是无参数方法
- SpEL注入:
Spring表达式语言全称为“Spring Expression Language” 缩写为“SpEL” 类似于Strus2x中使用的OGNL表达式语言,能在运行时期构建复杂表达式、存取对象属性、对象方法调用等。
可以在程序中单独使用,也可以在Spring应用中进行bean定义时使用。其核心是org.springframework.expression.Expression接口,Spring使用该接口来表示EL中的表达式。通过Expression接口的系列getValue()方法我们可以获取对应Expression在特定EvaluationContext下的值,也可以通过其系列setValue()方法来设值。 - Bean元素继承:
多个Bean元素共同配置的抽取,实则是bean配置的拷贝,和java的继承不同。
java的继承: 把多个类共同的代码抽取到父类中
bean元素的继承: 把多个bean元素共同的属性配置抽取到另一个公用的bean元素中。