活点地图
1.软件应用分层架构
- 标准三层架构
- 数据访问层:主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务.
- 业务逻辑层:主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建具体的讲主要负责对数据层的操作也就是说把一些数据层的操作进行组合
- 表示层:主要表示WEB方式,如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问
- 优点:
- 开发人员可以只关注整个结构中的其中某一层;
- 可以很容易的用新的实现来替换原有层次的实现;
- 可以降低层与层之间的依赖;
- 有利于标准化;
- 利于各层逻辑的复用
- 结构更加的明确
- 在后期维护的时候,极大地降低了维护成本和维护时间
- 缺点:
-
降低了系统的性能如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成
-
有时会导致级联的修改这种修改尤其体现在自上而下的方向如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码
-
增加了开发成本
思考:spring在项目中作用有哪些
2.Spring框架的相关概念
轻量级:spring是一种轻量级框架,spring给用户提供的功能完全有用户自己决定,用户想用什么功能需要自己去选择并使用(spring是一种模块化的框架)但是一般的重量级的框架都是只要你用,就把所有的功能都给你,用户不能自己定制
容器:spring框架中的容器可以管理项目中各种对象的生命周期(对象的创建、初始化、使用、销毁),前提是项目中要使用spring框架,并且把这些需要管理的对象配置给spring的容器
- spring框架给项目带来的好处
- 动态解藕,方便开发,面向接口设计
通过Spring提供的容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合 - 方便程序的测试
spring框架也提供了测试模块,可以和很多主流的测试框架相结合 - 降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个简单的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低 - 方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持 - AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程 - 声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量 - spring是一个模块化的项目,可以根据自己的需要定制功能模块
- spring的核心宗旨:简化企业级应用开发,同时给复杂问题提供强大的、非侵入性解决方案
3.Spring核心功能模块
-
Spring Core(spring的核心容器)
核心容器提供Spring框架的基本功能,Spring以bean的方式组织和管理Java应用中的各个组件及其关系,Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现BeanFactory使用控制反转(IOC)模式将应用的配置和依赖性规范与实际的应用程序代码分开BeanFactory使用依赖注入的方式提供给组件依赖 -
Spring Context(spring的上下文)
Spring上下文向Spring框架提供上下文信息Spring上下文包括各种信息和功能服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能 -
Spring Web
Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文Web层中使用的web框架可以是Spring自己的MVC框架,或者是其他的Web框架,如Struts、Webwork等 -
Spring DAO
一般三层架构中的DAO,主要目的是将持久层相关问题与一般的的业务规则隔离开Spring中的DAO模块提供了一致的方式访问数据库,不管采用何种持久化技术,Spring都提供一致的编程模型 -
Spring ORM
Spring与所有的主要的ORM映射框架都集成的很好,包括Hibernate、MyBatis等Spring为所有的这些框架提供了类似于模板的辅助类,达成一致的编程风格 -
Spring AOP(面向切面编程)
Spring AOP模块将面向切面编程的功能集成到了 Spring框架中所以,可以很容易的让Spring框架管理的对象都能支持AOP功能 -
Spring MVC(Spring WebMVC)
MVC框架是一个全功能的构建Web应用程序的MVC实现通过策略接口,MVC框架变成为高度可配置的Spring的MVC框架提供清晰的角色划分:控制器、验证器、命令对象、表单对象和模型对象、分发器、处理器映射和视图解析器当前个人主要学习的是spring Core和spring AOP,也就是spring框架所提供的ioc和aop功能
4.Spring中的IOC:
- IOC:Inversion of Control 控制反转
spring核心容器也可以称为IOC容器,该容器主要负责管理各种对象的声明周期(对象的创建、初始化、销毁等)
IOC容器并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了各种对象的可靠的管理,极大地降低了开发的复杂性。
思考1:是什么东西的"控制"被"反转"了?
思考2:自己组装电脑和直接购买整机的区别
总结:
1.IOC意味着将你设计好的类交给了spring容器去控制,而不是在类的内部自己进行控制。
2.有IOC容器之后,剩下的工作只是在IOC容器中堆积木
3.之前项目中对象和对象之间的关系是直接写死在代码中的,而使用了IOC容器后则是在代码中并没有写对象和对象是什么关系,而是把这种关系的建立交给了IOC容器去做,并且是在代码运行的时候动态建立起来(我们可以通过配置文件进行任意改变)
4.IOC其实就是一种将调用者与被调用者分离的思想(思考web层和service层和dao层的关系)
-
DI:Dependency Injection 依赖注入
DI的概念的提出是用来代替IOC的,表示让调用类对某一接口实现类的依赖关系由容器注入,以移除调用类对某一接口实现类的依赖。(思考servlet和service层接口以及service层接口实现类这三者的关系)
依赖注入 这个名词显然比 控制反转 更直接明了,并且易于理解。 -
DL:Dependency Loopup 依赖查找
容器创建对象并提供 回调接口和上下文环境 给这个对象,需要时通过接口从容器中查找其他对象
(之后会见到很多XxxxAware的接口,先简单理解即可)
5.Spring IOC容器核心api
(容器将来会是一个对象)
- BeanFactory接口
BeanFactory是Spring中IOC容器的核心接口,主要用于处理Bean的初始化和配置,建立对象间的依赖关系
接口中主要方法如下:
//根据指定名称返回一个Bean实例
Object getBean(String name)
//判断名称为name的Bean是否是原型,即是否总是返回一个新实例(非单例)
boolean isPrototype(String name)
//判断名称为name的Bean是否是单例
boolean isSingleton(String name)
//判断容器中是否包含给定名称的Bean实例
boolean containsBean(String name)
//如果名称为name的Bean有别名则返回别名
String[] getAliases(String name)
- ApplicationContext接口
该接口继承于BeanFactory,增强了BeanFactory,增加了事务处理AOP,国际化,事件传递等功能
所以在代码中我们一般会使用ApplicationContext接口,以及这个接口相应的实现类来创建spring的容器对象
例】
String path = "com/briup/ioc/set/set.xml";
ApplicationContext container = new ClassPathXmlApplicationContext(path);
Student s = (Student)container.getBean("student");
//使用s即可
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
注意事项:
1.这个文件的头部声明可以在下载的spring文档中的示例找到
2.在Eclipse中把xml文件和schema文件关联后,xml中就可以有标签代码的提示了(注意关联时别配置错了)
3.spring框架是模块化的,之后使用其他模块的时候,还可以在该xml的根元素中继续引用其他模块中相应的schema文件,然后就可以使用引入新模块中的标签代码了
7.IOC的相关功能
- 1.set方式注入(必须依靠set方法)
可以注入的内容有:
基本类型(8中基本类型+字符串)的装配
对象类型的装配
集合的装配
-
1)基本类型的装配
基本类型的装配 方式: 配置元素<value/> 例子: 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());
-
2)对象类型的装配
对象类型的装配 1.<ref local=" "/> 用于涉及的对象的id在本配置文件中 2.<ref bean=" "/> 用于涉及的对象的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();
-
3)集合的装配
集合的装配 方式:配置元素<list> <set> <map> <props> 例如: 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();
-
2.基于构造器注入
方式: 配置元素
在Bean中不用写set方法,但是要有相应的构造器
构造器注入有两种形式 一个是根据参数类型 一个是根据参数位置的下标
<constructor-arg type="int" value="">
<constructor-arg index="0" value="">
例如:
<bean name="student" class="com.briup.bean.Student">
<constructor-arg type="int" value="25">
</constructor-arg>
<constructor-arg type="java.lang.String" value="tom">
</constructor-arg>
<constructor-arg type="long" value="100">
</constructor-arg>
</bean>
或者:
<bean name="student" class="com.briup.bean.Student">
<constructor-arg index="2">
<value>30</value>
</constructor-arg>
<constructor-arg index="0">
<value>200</value>
</constructor-arg>
<constructor-arg index="1">
<value>lily</value>
</constructor-arg>
</bean>
-
3.自动注入
容器依照一些规则去装配bean中的一个属性
注意:自动装配只对[对象类型]起作用,对基本类型不起作用.第一种情况: 在beans标签中配置装载方式:default-autowire="byName" 在根元素beans中加入这个属性,那么下面所有的bean都会使用byName的方式进行自动注入, 如果在下面的某一个bean里面想使用其他的方式进行注入,可以用autowire=""属性进行说明, 或者某一个bean不想使用任何自动注入就使用autowire="no" 第二种情况: 在bean标签中指定配置方式 autowire="byName": spring容器会到当前的类中找property的名字, 然后再根据这个名字去spring容器中找有没有和这个property名字相同的对象,有的话,就把这个对象当做参数放到setXxxx这个方法里面注入进来. autowire="byType": spring容器会根据当前类中的set方法里面参数的类型, 去容器中找相匹配的对象,如果没找到就算了, 如果找到一个就注入进来,如果找到多个,那么就会报错了. autowire="constructor" 根据构造器的参数类型去匹配
-
4.继承
配置文件中,一个bean的配置可以继承另一个bean的配置bean标签中的两个属性: abstract属性 <bean name=".." class=".." abstract="true"> 注:bean中一旦定义为了abstract="true",则说明该bean是用来被继承的, 不能通过该bean获得对象了 parent属性,指定继承哪个bean的配置 <bean name=".." parent="另一个bean的名字"> 例子: <bean name="student" class="com.briup.bean.Student"> <property name="name"> <value>zhangsan</value> </property> </bean> <!-- abstract="true" 表示当前的配置是一个抽象的配置, 这时候我们在代码中就不能通过这个bean的名字teacher来获得相应的对象了 (和java中的抽象类不能直接new对象的道理一样) 但是我们可以在写一个配置去继承这个抽象的配置,当然即使当前 这个配置不是抽象的,也能够被继承(和java中继承一样)--> <bean name="teacher" class="com.briup.bean.Teacher" abstract="true"> <property name="student" ref="student"></property> </bean> <!-- parent="teacher" 表示当前配置是继承了另外一个名字叫teacher的bean的配置, 配置和配置的继承像java中的类和类直接的继承一样, 子类会把父类中的对象继承过来。 当然在子配置里面依然是可以覆盖父配置中已经写的配置信息.--> <bean name="t" parent="teacher"> <property name="id"> <value>11</value> </property> <property name="name"> <value>TeacherWang</value> </property> </bean>
8 Bean对象的在IOC容器中的生命周期
例如:我们需要从容器中获得一个Bean的对象:
1、容器创建该Bean的对象
2、容器给这个Bean对象注入依赖
3、如果这个Bean已经实现了BeanNameAware接口,容器会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id/name值
4、如果这个Bean已经实现了BeanFactoryAware接口,容器会调用它实现的setBeanFactory方法
该方法接收的参数就是容器本身(可以用这个方式来获取其它Bean)
5、如果这个Bean已经实现了ApplicationContextAware接口,容器会调用setApplicationContext方法,该步和第四步类似,ApplicationContext是BeanFactory的子接口,有更多的实现方法
6、如果spring容器中配置了BeanPostProcessor接口的实现类,容器将会调用该实现类中的postProcessBeforeInitialization方法,表示可以在Bean对象执行 初始化方法之前 做点事情
7、如果Bean在Spring配置文件中配置了init-method属性则会自动调用其配置的初始化方法
8、如果spring容器中配置了BeanPostProcessor接口的实现类,容器将会调用该实现类中的postProcessAfterInitialization方法,表示可以在Bean对象执行 初始化方法之后 做点事情
注:以上工作完成以后就可以使用这个Bean对象了
9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
但是一般情况下,我们定义的Bean都是些普通的类,没有用到任何spring的接口,所以大多数时候我们只考虑Bean对象的创建、依赖注入、初始化、使用、销毁即可,并且可以把Bean分为单例和非单例俩种情况:
单例管理的对象:
1.默认情况下,spring在读取xml文件的时候,就会创建对象
2.进行依赖注入,如果有依赖的话
3.会去调用init-method=".."属性值中所指定的方法,如果有该配置的话
4.Bean对象可以被正常使用
5.对象在被销毁的时候,会调用destroy-method="..."属性值中所指定的方法,如果有该配置的话
注意1:调用container.destroy()方法会销毁单例对象
注意2:lazy-init="true",可以让这个Bean对象在第一次被访问的时候创建,而不是读取xml文件就被创建
注意3:因为是单例,所以该对象只会被创建一次
非单例管理的对象:
1.使用这个对象的时候,spring容器会创建这个对象
2.进行依赖注入,如果有依赖的话
3.会去调用init-method=".."属性值中所指定的方法,如果有该配置的话
4.Bean对象可以被正常使用
注意1:spring容器不会销毁非单例对象
注意2:因为是非单例,所以每次使用都会创建一个新的Bean对象