从三层架构到Spring框架
2019-10-25 06:56:42来源:博客园 阅读 ()
从三层架构到Spring框架
首先是软件的应用分层架构
标准三层架构:
1:数据访问层:实现了数据的持久化
2:业务逻辑层:对逻辑的实现及处理,实际上不可能在表示层对数据不做任何处理,但是尽可能的将逻辑分为一层
3:表示层:数据的展示
优点:
降低了一个程序的耦合度,一个类中有一千行代码可以转化为三个类中各写300多行代码,每个类实现自己的功能
慢慢的就形成了一种标准化趋势,更加的适应于面向接口编程,注重《开闭原则》的实现,对修改关闭,而对扩展开放,
扩展的功能定义为接口,程序员进行实现,在现有的代码中组合进新功能的实现类对象,从而实现新功能的添加。
缺点:
然而这种三层体系架构依旧存在一些问题
1.有些时候将简单的问题复杂化,假如:
一个类300代码可以完成的工作,分为三层架构后每个类需要120行代码进行完成,反而得不偿失了
2.组合的代码不一定有效,例如:
有这样一个类:
public class A{ private IB b=new BImpl(); public void go(){ b.go(); } public static void main(String agrs[]){ new A().go(); } }
这个例子可以看出,一旦IB接口的实现类BImpl出现了问题,那么b.go()可能空指针异常,A类中的方法就无法正常运行
那么:有没有一种方法可以不使用组合的方式来获得对象?
Java中创建对象对象除了new关键字之外,有的就是反射机制了。有效的破坏莫不失为一种好想法,有了反射我们就可以直接通过权限定名来创建对象。
Spring框架的相关概念
轻量级:spring是一种轻量级框架,用户可以自定义自己需要的内容,选择自己需要的功能模块
容器的概念:
Java开发中常见的容器有:GUI,Tomcat都是一些容器,比如jsp动态页面的展示,就是需要Tomcat容器的支持才可以运行。spring框架中的容器可以管理项目中各种对象的生命周期(对象的创建、初始化、使用、销毁)
前提是项目中要使用spring框架,并且把这些需要管理的对象配置给spring的容器,常见的IOC容器可以控制bean对象的
但是这个bean对象一般都是单例的。
生成生命周期,当然前提是对象不可以脱离容器控制范围(单例对象和多例对象)
spring框架给项目带来的好处:
1)动态解藕,方便开发,面向接口设计
我们可以将对象之间的依赖关系交由Spring进行控制
2)方便程序的测试
spring框架也提供了测试模块,可以和很多主流的测试框架相结合
3)降低Java EE API的使用难度
Spring封装了如jdbc等许多有难度的操作,使得代码“相对”精简。
这里的相对是说,使用了框架相当于在项目中已经引入了代码,所以说Java之所以有许多人用,那是因为Java的类库太丰富了
Spring功能足够强大,但是又可以自己选择模块,这就十分人性化了。
但是Java在程序的效率方面来说是比不上C和C++了。
4)方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度
Spring提供了对各种优秀框架(如Struts,Hibernate,MyBatis)等的直接支持
5)AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程
6)声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量
7)spring是一个模块化的项目,可以根据自己的需要定制功能模块
spring的核心宗旨:简化企业级应用开发,同时给复杂问题提供强大的、非侵入性解决方案
Spring核心功能模块 Spring Framework
在Spring Framework中又分为许多的模块
Spring Context(spring的上下文)
Spring Web
Spring DAO
Spring ORM
Spring AOP(面向切面编程)
Spring MVC(Spring WebMVC)
Spring Core(spring的核心容器)
这个容器是Spring的一个核心容器
我当前主要学习了的是spring Core和spring AOP,也就是spring框架所提供的ioc和aop功能
Spring MVC是一个集成化的web开发框架,不恰当的说它的地位甚至可以将其从Spring中分离出来,作为一个单独的框架
spring中的IOC
IOC:Inversion of Control 控制反转
spring核心容器也可以称为IOC容器,该容器主要负责管理各种对象的生命周期(对象的创建、初始化、销毁等)
IOC容器并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象
而且提供了各种对象的可靠的管理,极大地降低了开发的复杂性。
思考1:是什么东西的"控制"被"反转"了?
简单的说:是对象被控制了起来,创建对象的操作反转给了框架
思考2:自己组装电脑和直接购买整机的区别
DI:Dependency Injection 依赖注入
DI的概念的提出是用来代替IOC的,表示让调用类对某一接口实现类的依赖关系由容器注入,以移除调用类对某一接口实现类的依赖。(思考servlet和service层接口以及service层接口实现类这三者的关系)
依赖注入 这个名词显然比 控制反转 更直接明了,并且易于理解。
DL:Dependency Loopup 依赖查找
容器创建对象并提供 回调接口和上下文环境 给这个对象,需要时通过接口从容器中查找其他对象
(之后会见到很多XxxxAware的接口,先简单理解即可)
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即可
三层关系如下:
BeanFactory
↑
ApplicationContext
↑
ClassPathXmlApplicationContext
配置文件
这是一个框架中必不可少的部分,会写Spring的XML文件一定会用Spring框架,但是会用不一定明白为什么这么用......
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>
IOC的相关功能
IOC实际上就是实现的Spring容器帮助我们管理对象的功能,所以要先从如何将对象注入到容器中来学习
注入有两种方式:set注入和构造器注入,自动注入和继承也属于这个知识点内
set方式注入(必须依靠set方法)
顾名思义,实现set方式的注入就必须存在set方法
这种动态代理的方式创建对象是反射机制,如果是set注入就必须要无参构造器的支持
可以注入的内容有:
1基本类型(8中基本类型+字符串)的装配
2对象类型的装配
3集合的装配
1.基本类型的装配
方式: 配置元素<value/>
例子:
public class HelloBean { private String name; private int age; public String sayHello(){ return "hello "+name +",your age is" + age; } ............. }
配置文件set.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"> <bean id="helloBean" class="ioc.HelloBean"> <property name="name"> <value>tom</value> </property> <property name="age" value="20"> </property> </bean> </beans>
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属性引用,这样就不需要处理涉及到的对象在不在同一个xml配置文件中
例如:
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=" "/> 用于涉及的对象的id不在本配置文件中 --> <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; get/set...... toString(); }
applicationContext.xml的写法:
<bean id="someBean" class="ioc.SomeBean"> <property name="listProperty"> <list> <value>list1</value> <value>list2</value> <value>list3</value> </list> </property> <property name="setProperty"> <set> <value>set1</value> <value>set2</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();
基于构造器注入
方式: 配置<constructor-arg>元素
在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>
构造器注入有俩种形式 一个是根据参数类型 一个是根据参数位置的下标
还有指定参数传参 这里的name指的是形参的参数名字
<bean name="student" class="com.briup.bean.Student"> <constructor-arg index="0" value="2" name="a"></constructor-arg> <constructor-arg index="1" value="3" name="b"></constructor-arg> <constructor-arg index="2" value="4" name="c"></constructor-arg> </bean>
自动注入 :容器依照一些规则去装配bean中的一个属性
注意:自动装配只对[对象类型]起作用,对基本类型不起作用.
第一种情况:
在beans标签中配置装载方式:default-autowire="byName"
在根元素beans中加入这个属性,那么下面所有的bean都会
使用byName的方式进行自动注入,如果在下面的某一个bean
里面想使用其他的方式进行注入,可以用autowire=""属性进行
说明,或者某一个bean不想使用任何自动注入就使用autowire="no"
第二种情况:
在bean标签中指定配置方式
autowire="byName":
spring容器会到当前的类中找property的名字,然后
再根据这个名字去spring容器中找有没有和这个property
名字相同的对象,有的话,就把这个对象当做参数放到
setXxxx这个方法里面注入进来.
比如Teacher类中有一个属性Student student
对应的有setStudent()方法
在xml中配置了Student这个类。
name="studnet";
Spring在自动注入Teacher类中的student属性的时候就会去找和这个property
名字相同的对象
<bean name="t" class="com.briup.bean.Teacher" autowire="byName">
<property name="id" value="10"></property>
<property name="name" value="王老师"></property>
<!-- <property name="student" ref="stu"></property> -->
</bean>
注意:了解property指的类中的什么东西
property来源于attribute
property name="xxxx"实际上就是setXxxx()
这四个xxxx是一个含义
autowire="byType":
spring容器会根据当前类中的set方法里面参数的类型,
去容器中找相匹配的对象,如果没找到就算了,如果找到
一个就注入进来,如果找到多个,那么就会报错了.
也就是说找不到大不了就赋值为null,但是找到两个框架报错了,因为框架不知道用哪个啊
所以说要么就不写,写了就不要有歧义。
autowire="constructor"
根据构造器的参数类型去匹配
继承
配置文件中,一个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>
原文链接:https://www.cnblogs.com/Magic-Li/p/11722976.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Spring系列.ApplicationContext接口 2020-06-11
- springboot2配置JavaMelody与springMVC配置JavaMelody 2020-06-11
- 老板让你抗住千万级流量,如何做架构设计? 2020-06-11
- 给你一份超详细 Spring Boot 知识清单 2020-06-11
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash