文章目录
Spring
轻量级(对比EJB)、解决方案、整合了很多的设计模式
设计模式
- 面向对象设计中,解决特定问题的经典代码
- 狭义上指:GOF四人定义的23中设计模式
工厂模式
通过工厂类创建对象
解耦,避免硬编码
核心API
ApplicationContext(工厂)
- 用于对象的创建
- 接口:屏蔽实现的差异(主要有两种实现)
- 非Web环境:ClassPathXmlApplicationContext
- Web环境:XmlWebApplicationContext(需要导入spring-webmvc)
- ApplicationContext工厂对象占用大量内存(重量级资源):一个应用只会创建一个工厂对象
- 线程安全的:多线程并发访问
ApplicationContext的方法
bean = component
getBean()
:有三个重载getBeanDefinitionNames
:获取bean的id值getBeanNamesForType
:指定类型的id值containsBeanDefinition
:是否存在id(只判断id)containsBean
:是否存在id或者name(判断id和name)
配置文件
- 可以没有省略id,Spring会自动生成一个
全限定名#0
- id是唯一的,有命名的要求(XML的历史要求,如今已经不限制了)
- name可以有多个值,使用
,
隔开(用得少) containsBeanDefinition
和containsBean
有区别
注入(Injection)
解耦合
- Set注入
- 构造注入
Set注入
<bean class="com.tonkia.Person">
<property name="id" value="1"/>
<property name="name" value="tonkia"/>
</bean>
- JDK内置类型
- 8种基本类型 + String
- 数组
- Set
- List
- Map
- Properties
- 用户自定义类型
- 复杂的JDK类型(Date):自定义类型转换器
p命名空间
<bean id="classRoom" class="com.tonkia.ClassRoom"/>
<bean class="com.tonkia.Person" p:id="1" p:name="tonkia" p:classroom-ref="classRoom"/>
构造注入
<bean class="com.tonkia.Customer">
<constructor-arg>
<value>tonkia</value>
</constructor-arg>
<constructor-arg>
<value>12</value>
</constructor-arg>
</bean>
- 构造参数不同:通过
<constructor-arg>
的个数区分 - 构造参数相同:指定type来区分
反转控制(IoC)
Inverse of Control
- 控制:对于成员变量赋值的控制权
- 反转控制:把对于成员变量赋值的控制权从代码中转移(反转)到Spring工厂和配置文件中完成
- 底层实现:工厂设计模式
依赖注入(Dependency Injection,DI)
反转控制是一种概念,通过DI实现IoC
复杂对象
不能之间通过new方法创建的对象
例如:Connection、SqlSessionFactory
创建的三种方式
- FactoryBean接口
- 实例工厂
- 静态工厂
FactoryBean接口
- 实现FactoryBean接口
public class TestFactoryBean implements FactoryBean<Person> {
@Override
public Person getObject() throws Exception {
Person p =new Person();
p.setClassroom(new ClassRoom());
p.setName("fb");
p.setId(100);
return p;
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
- 配置文件
<bean id="factoryBean" class="com.tonkia.TestFactoryBean"/>
- 获取对象
获取复杂对象
applicationContext.getBean(“factoryBean”);
获取FactoryBean对象
applicationContext.getBean("&factoryBean");
实例工厂
- 避免Spring侵入(实现FactoryBean接口)
- 整合遗留系统
<bean id="factoryBean" class="com.tonkia.TestFactoryBean"/>
<bean id="person" factory-bean="factoryBean" factory-method="getObject"/>
静态工厂
<bean class="com.tonkia.StaticFactoryBean" factory-method="getObject"/>
控制Spring工厂创建次数
- 节省内存空间
简单对象
scope
- singleton(default)
- prototype
复杂对象
- FactoryBean:isSingleton方法返回值
- 实例工厂、静态工厂:scope
对象生命周期
创建、存活、消亡
对象创建
singleton:默认容器创建的时候创建单例对象,除非指定lazy-init="true"
prototype:获取对象的时候创建对象
初始化阶段
创建完对象(属性注入)后,进行初始化
在初始化方法中进行资源的初始化
实现InitializingBean
接口
public class ClassRoom implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
}
}
无侵入的方法:指定初始化方法
<bean class="com.tonkia.ClassRoom" init-method="init"/>
销毁阶段
发生在工厂关闭(显示close:applicationContext.close()
)的时候,进行资源释放回收
只适用于singleton,prototype不起作用
- 实现DisposableBean
public class ClassRoom implements DisposableBean, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
}
@Override
public void destroy() throws Exception {
}
}
- 指定
distory-method
<bean class="com.tonkia.ClassRoom" init-method="myInit" destroy-method="myDestory"/>
执行顺序
public class ClassRoom implements DisposableBean, InitializingBean {
private String className;
public void setClassName(String className) {
System.out.println("ClassRoom.set");
this.className = className;
}
public ClassRoom() {
System.out.println("ClassRoom.constructor");
}
public void myInit() {
System.out.println("ClassRoom.myInit");
}
public void myDestory() {
System.out.println("ClassRoom.myDestory");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("ClassRoom.afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("ClassRoom.destroy");
}
}
<bean class="com.tonkia.ClassRoom" init-method="myInit" destroy-method="myDestory">
<property name="className" value="math"/>
</bean>
配置文件参数化
<context:property-placeholder location="classpath:/config.properties"/>
自定义类型转换器
注入过程中将String类型转换为对应的类型
例如:将String转换为Date类型(Spring只提供了yyyy/MM/dd
)
- 实现Converter接口
public class MyConverter implements Converter<String, Date> {
private SimpleDateFormat pattern = new SimpleDateFormat("yyyy-MM-dd");
public void setPattern(String pattern) {
this.pattern = new SimpleDateFormat(pattern);
}
@Override
public Date convert(String s) {
Date d = null;
try {
d = pattern.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return d;
}
}
- 在配置文件中注册
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.tonkia.MyConverter">
<property name="pattern" value="yyyy-MM-dd"/>
</bean>
</set>
</property>
</bean>
<bean class="com.tonkia.Product">
<property name="id" value="1"></property>
<property name="birthday" value="1996-10-03"></property>
</bean>
其中id值必须为conversionService
BeanPostProcessor
对Spring工厂创建的对象进行再加工
AOP底层实现
postProcessBeforeInitialization
:set后init前postProcessAfterInitialization
:init后