spring framework
1.背景介绍
代码的三层架构:
实现高内聚,低耦合
web:表示层,与用户交互,依赖service,手动创建对象
service:业务逻辑层,处理业务逻辑
dao:数据访问层,与数据库交互
上层对下层的调用:面向接口/抽象编程
下层对上层的真正服务提供:实现类
模块和模块之间,对象和对象之间,手动在代码中书写,建立关系。
spring:
-
尽量解耦,管理需要管理的对象,包括对象的创建,初始化,装配(维护对象与对象之间的关系),销毁(生命周期),不需要在代码中–IoC
-
事务管理–AOP
2.相关概念
2.1轻量级容器
容器:spring容器帮我们管理业务逻辑层,里边有很多业务逻辑对象,有对象就有对象的生命周期的管理(创建,销毁)。
轻量级:容器给予的业务逻辑对象多少种服务?spring给用户提供的服务完全有用户自己决定,spring想用什么服务自己开启使用。但是重量级的都是只要你用就把所有的服务都给你,不能自己定制。
特点:应用模块之间耦合度小,组件都是可重用的,都是各自打包的
why spring?
1)动态解藕,方便开发,面向接口设计
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用
2)方便程序的测试
3)降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个简单的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
4)方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
5)AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
6)声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
7)spring是一个模块化的项目,可以根据自己的需要定制功能模块
spring的核心宗旨:简化企业级应用开发,同时给复杂问题提供强大的、非侵入性解决方案
一站式的解决方案
3.核心组件
(1)、Spring Core(IOC) 核心容器,提供组件的创建、装备、销毁(管理对象)
(2)、Spring Context Spring上下文,是一个接口ApplicationContext(继承自BeanFactory接口)的实现
(3)、Spring Web容器,web应用上下文,是webApplicationContext接口的实现
(4)、Spring DAO容器,是SpringDAO 支持模块,是为了简化DAO的使用
(5)、Spring ORM
(6)、Spring AOP ,对AOP编程支持的模块
(7)、Spring MVC,类似于Spring表示层的一个框架
4.Spring IoC
Inversion of Control:控制反转
一种说法:对象之间的依赖关系,由容器在运行时依据配置文件动态的建立
另一种说法:对象的控制器转移了,转到外部容器了,避免了代码的纠缠,代码更容易被维护,模板之间的耦合性降低,容易测试
IoC 控制反转意味着将你设计好的类交给容器去控制,而不是在类的内部进行控制,即控制权由应用代码中转到了外部容器
IoC:包括两部分内容
DI:Dependency Injection依赖注入,组件不做定位查询,只提供相应方法,由容器创建对象,并调用相应方法设置所需对象需要的组件(要求掌握)
A a = new A(); B b = new B(); a.setXXX(b) ---由spring实现
DL:Dependency Loopup依赖查找,容器创建对象并提供回调接口和上下文环境给组件,需要时通过接口从容器中查找对象(理解即可) (之后会见到很多XxxxAware的接口)
org.springframework.beans包和org.springframework.context包是IOC容器的基础包
5.Spring IoC 核心api
5.1BeanFactory接口和容器
BeanFactory是Spring中Bean容器,IoC的核心接口,主要用于处理Bean(可重用“组件(对象)”)的初始化和配置,建立对象间的依赖关系
定义了如下方法:
Object getBean(String name) //根据指定名称返回一个Bean实例
在Spring中,同一Spring容器中的bean默认情况下是Singleton(单例).
5.2ApplicationContext接口
该接口继承于BeanFactory,增强了BeanFactory,提供了事务处理AOP,国际化,事件传递
所以在代码中我们一般会使用ApplicationContext接口,以及这个接口相应的实现类来创建spring的容器对象。
例如:
String path = "com/ioc/set/set.xml";
ApplicationContext container = new ClassPathXmlApplicationContext(path);
6.配置文件
Spring通过读取配置文件中的数据来对应用中各个对象进行实例化,配置以及组装,通常使用XML文件来作为配置文件。
XML基本结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
</beans>
这个文件的头部声明可以在下载的spring文档中的示例找到.注意这里面用到了俩个schema文件(.xsd文件),就是spring-beans-3.2.xsd和spring-context-3.2.xsd,这俩个文件在下载的spring文档中也是可以找到的.我们在Eclipse中把xml文件和schema文件关联后,在这个xml中就可以有智能提示了。还有一点需要注意,将来我们这xml中再引入另外的schema文件后在配置的时候就可以智能提示出新的配置内容,spring是又很多模块组成的,我们需要什么功能的配置标签就需要引入对应的schema文件,从而获得智能提示,同时也能帮我们验证配置的正确性
问题1:如何通过[读取]配置文件[一个或多个对象的相关配置]创建对象[需要管理的对象]并建立对象与对象的依赖关系[ioc–DI]?
1.1读取配置文件 dom4j
1.2获取根标签beans,获取bean(list存)
1.3获取bean标签的name(beanName),class(通过class创建对象Object)
Map方式存 map<beanName,Object>
1.4 property name--通过name得到setXXX方法(反射) ref--map.get("stu"),获取关联对象
method.invoke(t,stu)
7.IOC注入
7.1 set方式注入
可以注入的内容有:
A、基本类型(8中基本类型+字符串)的装配
B、对象类型的装配
C、集合的装配
A、基本类型的装配
方式: 配置元素
例子:
public class HelloBean {
private String name;
private int age;
public String sayHello(){
return "hello "+name +",your age is" + age;
}
.............
}
配置文件set.xml
<bean id="helloBean" class="ioc.HelloBean">
<property name="name">
<value>tom</value>
</property>
<property name="age" value="20">
</property>
</bean>
<!--
id是Bean的唯一标识,要求在整个配置文件中要唯一,也可使用name属性,bean标签里面的id和name属性都可以用来标识这个配置的对象,
但是id会帮我们检查给对象起的名字是否规范(名字不能重复、不能用数字开头、不能有空格等等),如果检查出来了那么就会报错。name属性不会帮检查这些东西(某些版本)。
-->
<!--property 对于所有用set方式来注入的必须使用该标签-->
<!--value 是对以基本类型,都用value(标签/属性)来注入,可以实现自动的数据类型转换-->
测试类:
main:
ApplicationContext ac =
new ClassPathXmlApplicationContext("set.xml");
//获取容器的一个实例
HelloBean hb = (HelloBean) ac.getBean("helloBean");
System.out.println(hb.sayHello());
B、对象类型的装配
(1)、 用于涉及的对象的id在本配置文件中
(2)、 用于涉及的对象的id不在本配置文件中
(3)、使用property的ref属性引用
public class OtherBean {
private String str1;
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String toString(){
return "OtherBean "+str1;
}
}
public class SomeBean {
private OtherBean ob;
public void printInfo(){
System.out.println("someBean "+ob);
}
public OtherBean getOb() {
return ob;
}
public void setOb(OtherBean ob) {
this.ob = ob;
}
}
配置applicationContext.xml
<bean id="someBean" class="ioc.SomeBean">
<property name="ob">
<ref bean="otherBean" />
</property>
</bean>
配置other.xml文件
<bean id="otherBean" class="ioc.OtherBean">
<property name="str1">
<value>hello</value>
</property>
</bean>
测试类:
main:
String[] path = {"ioc/applicationContext.xml","ioc/other.xml"};
ApplicationContext ac = new ClassPathXmlApplicationContext(path);
SomeBean sb = (SomeBean) ac.getBean("someBean");
sb.printInfo();
C、集合的装配
方式:配置元素
public class SomeBean {
private List listProperty;
private Set setProperty;
private Map mapProperty;
private Properties<String,String> property;
public List getListProperty() {
return listProperty;
}
public void setListProperty(List listProperty) {
this.listProperty = listProperty;
}
public Set getSetProperty() {
return setProperty;
}
public void setSetProperty(Set setProperty) {
this.setProperty = setProperty;
}
public Map getMapProperty() {
return mapProperty;
}
public void setMapProperty(Map mapProperty) {
this.mapProperty = mapProperty;
}
public Properties getProperty() {
return property;
}
public void setProperty(Properties property) {
this.property = property;
}
public void printInfo(){
System.out.println("listProperty");
System.out.println(listProperty);
System.out.println("setProperty");
System.out.println(setProperty);
Set set = mapProperty.entrySet();
Iterator it = set.iterator();
while(it.hasNext()){
Map.Entry entry = (Entry) it.next();
System.out.println("Key " +entry.getKey() );
System.out.println("value "+entry.getValue());
}
System.out.println("props: ");
Set set2 = property.entrySet();
Iterator it2 = set2.iterator();
while(it2.hasNext()){
Map.Entry entry= (Entry) it2.next();
System.out.println("key "+entry.getKey());
System.out.println("value "+entry.getValue());
}
}
}
applcationContext.xml的写法:
<bean id="someBean" class="ioc.SomeBean">
<property name="listProperty">
<list>
<value>list1</value>
<value>list1</value>
<value>list3</value>
</list>
</property>
<property name="setProperty">
<set>
<value>set1</value>
<value>set1</value>
<value>set3</value>
</set>
</property>
<property name="mapProperty">
<map>
<entry key="key1">
<value>value1</value>
</entry>
<entry key="key2">
<value>value2</value>
</entry>
</map>
</property>
<property name="property">
<props>
<prop key="key1">prop1</prop>
<prop key="key2">prop2</prop>
<prop key="key3">prop3</prop>
</props>
</property>
</bean>
测试类:
main:
String path = "ioc/applicationContext.xml";
ApplicationContext ac =
new ClassPathXmlApplicationContext(path);
SomeBean sb = (SomeBean) ac.getBean("someBean");
sb.printInfo();