Spring架构设计图
Spring架构主要分为 核心容器模块,Web/Remoting模块,数据访问/集成模块,Test模块
核心容器:包括Core、Beans、Context、EL模块。
数据访问/集成模块:该模块包括了JDBC、ORM、OXM、JMS和事务管理
Web/Remoting模块:Web/Remoting模块包含了Web、Web-Servlet、Web-Struts、Web-Porlet模块。
Test模块: Spring支持Junit和TestNG测试框架,而且还额外提供了一些基于Spring的测试功能,比如在测试Web框架时,模拟Http请求的功能
Ioc—Inversion of Control,即“控制反转”
控制:IoC是有专门一个容器来创建对象,即由Ioc容器来控制对象的创建。创建对象的过程的控制权由程序员转移给了IOC容器。
反转:手动创建对象时是主动控制直接去获取该对象创建所需要依赖的其他资源或者对象,而反转则是由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转。
把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
传统应用程序示意图
有IoC/DI容器后程序结构示意图
IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖, 在Spring中BeanFactory是IoC容器的实际代表者。
Spring IoC容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配。一般使用XML配置元数据。可用其他方式:如注解,属性文件之类配置都可。
由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean, Bean就是由Spring容器初始化、装配及管理的对象,在spring配置文件中来配置元数据,指定如何实例化,组装Bean。
在Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口
ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现
Bean的实现:
//ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");
//FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");
//XmlWebApplicationContext:从Web系统中的XML文件来载入Bean定义的信息。
ServletContext servletContext = request.getSession().getServletContext();
ApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
ApplicationContext接口获取Bean
Object context.getBean(name);
一、准备配置文件:就像前边Hello World配置文件一样,在配置文件中声明Bean定义也就是为Bean配置元数据。
二、由IoC容器进行解析元数据: IoC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IoC容器根据BeanDefinition进行实例化、配置及组装Bean。
三、实例化IoC容器:由客户端实例化容器,获取需要的Bean
1、不指定id,只配置必须的全限定类名,由IoC容器为其生成一个标识,客户端必须通过接口
“T getBean(Class< T > requiredType)”获取Bean;
< bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
HelloApi helloApi = beanFactory.getBean(HelloApi.class);
2、指定id,必须在Ioc容器中唯一;
< bean id="bean" class="cn.javass.spring.chapter2.helloworld.HelloImpl" />
//根据id获取bean
HelloApi bean = beanFactory.getBean("bean", HelloApi.class);
3、指定name,这样name就是“标识符”,必须在Ioc容器中唯一;
<bean name="bean" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
//根据name获取bean
HelloApi bean = beanFactory.getBean("bean", HelloApi.class);
在XML中id是一个真正的XML id属性,因此当其他的定义来引用这个id时就体现出id的好处了,可以利用XML解析器来验证引用的这个id是否存在,从而更早的发现是否引用了一个不 存在的bean,而使用name,则可能要在真正使用bean时才能发现引用一个不存在的bean。
Spring IoC容器则需要根据Bean定义里的配置元数据使用反射机制来创建Bean。
< bean name="bean2" class="cn.javass.spring.chapter2.HelloImpl2">
<!-- 指定构造器参数 -->
< constructor-arg index="0" value="Hello Spring!"/>
</ bean>
使用< constructor-arg >标签指定构造器参数值,其中index表示位置,value表示常量值,
除了指定必须的class属性,还要指定factory-method属性来指定实例化Bean的方法,而且使用静态工厂方法也允许指定方法参数
静态工厂:
public class HelloApiStaticFactory {
//工厂方法
public static HelloApi newInstance(String message) {
//返回需要的Bean实例
return new HelloImpl2(message);
}
}
<!-- 使用静态工厂方法 -->
< bean id="bean3" class="cn.javass.spring.chapter2.HelloApiStaticFactory"
factory-method="newInstance">
<constructor-arg index="0" value="Hello Spring!"/>
</bean>
HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);
不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法,而且使用实例工厂方法允许指定方法参数,方式和使用构造器方式一样
public class HelloApiInstanceFactory {
public HelloApi newInstance(String message) {
return new HelloImpl2(message);
}
}
<!—1、定义实例工厂Bean -->
<bean id="beanInstanceFactory"
class="cn.javass.spring.chapter2.HelloApiInstanceFactory"/>
<!—2、使用实例工厂Bean创建Bean -->
<bean id="bean4"
factory-bean="beanInstanceFactory"
factory-method="newInstance">
<constructor-arg index="0" value="Hello Spring!"></constructor-arg>
</bean>
HelloApi bean4 = beanFactory.getBean("bean4", HelloApi.class);
因篇幅问题不能全部显示,请点此查看更多更全内容