框架前奏
穿插之前的JAVAWEB项目,之后的Spring框架。
JAVAWEB项目:用到技术点
- MVC模式
- 数据库连接技术(JDBC)
- 分层思想
1.先创建JAVAWEB项目(IDEA)
使用tomcat,配置运行一下
2.src下的目录
某新闻系统,主题为例,Topic
搭建框架
- com.aaa.dao:数据访问层的包
- com.aaa.dao.impl:数据访问层接口的实现类
- com.aaa.service:业务层的包,主要放业务层接口
- com.aaa.service.impl:业务层包的实现类:主要放业务层接口实现类
- com.aaa.controller:Servlet,去调用业务层的接口及其实现类。
controller是之前的写法,今天的测试,换成了一个test包,在test包下建立一个test类,来测试业务层接口及其实现类。
这个其实和使用servlet测试是一样。
刚才我们讲了,搭建。在控制台做了测试输出。
3.setter解耦
数据库mysql,oracle
有mysql的数据访问层的实现,有oracle的数据访问层的实现。
业务层,这里实现的是TopicDaoMysqlImpl,针对的mysql数据库的操作。
我们现在的操作都变了,要去操作oracle数据库。怎么办呢???
TopicDao topicDao=new TopicDaoMysqlImpl();
代码改变:
TopicDao topicDao=new TopicDaoOracleImpl();
运行之后,可以看到,会改变为删除oracle数据库中的主题编号:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GKiyCtrG-1591145306194)(E:\政通路\课堂笔记\S2\Spring\assets\image-20200601163742411.png)]y
大家要总结一下,当我们的数据库变更的时候,这样操作的方式好不好呢???
假如说,我们的项目已经部署上线了,项目在运行,你来改变代码来了。不能说肯定会出现问题,但是出现问题的几率一定是比较大。
能不能有一种方式,由客户自己来决定变更使用哪种数据库或者是客户自己决定某种操作。
这种问题,其实就是程序的耦合问题。
之前学习过OOP,三大特征:封装、继承、多态。
要实现的目标是:高内聚、低耦合、高复用
我们在写程序的时候,尽量低耦合。不new具体的对象;
重点代码:
package com.aaa.service.impl; import com.aaa.dao.TopicDao; import com.aaa.dao.impl.TopicDaoMysqlImpl; import com.aaa.dao.impl.TopicDaoOracleImpl; import com.aaa.service.TopicService; /** * Created by 张晨光 on 2020/6/1 16:19 * 主题业务层的实现类;java程序员 调用dao层,不改. * 调用dao层的接口及其实现; */ public class TopicServiceImpl implements TopicService { //定义dao层对象,及其实现类; //TopicDao topicDao=new TopicDaoMysqlImpl(); //TopicDao topicDao=new TopicDaoOracleImpl(); //这种方式:是通过new 出来dao层对象的具体的实现类。 //能不能有一种方式,交由客户自己来调用的时候来实现呢??? //尽量少的动代码; //这种其实就是程序之间的耦合问题。 //********************松耦合的实现************ TopicDao topicDao; //创建它的getter/setter public TopicDao getTopicDao() { return topicDao; } //重点看这个:参数是一个TopicDao的对象; public void setTopicDao(TopicDao topicDao) { this.topicDao = topicDao; } @Override public void deleteTopicById(Integer id) { //在方法里面,通过dao层对象去执行删除操作; //注意看:这里面有topicDao的对象的new ???没有了 topicDao.deleteTopicById(id); } }
客户端的使用:
TopicService topicService=new TopicServiceImpl(); //在业务层实现类代码里面,已经没有了new TopicDaoOracleImpl的代码,我们的目标就是去掉这个 //代码,实现松耦合 //通过setter来实现 //((TopicServiceImpl) topicService).setTopicDao(new TopicDaoOracleImpl()); //客户变更为了mysql ((TopicServiceImpl) topicService).setTopicDao(new TopicDaoMysqlImpl()); //由原来在业务层实现类的具体的new xxxImpl,交由客户端test类自动选择,我要new。 // topicService.deleteTopicById(3);//模拟实现;
总结:
- 耦合度:模块间的耦合度是指模块之间的依赖关系;java里面的耦合度指的是类、接口、实现之间的关联程度。
- 解耦:通过把创建接口对象的setter()方法,在客户端由客户决定哪种数据库的使用。
- 高内聚:尽可能类的每个成员方法只完成一件事(最大限度的聚合)
- 之前的数据库连接代码,放在了BaseDao里面,是写死的,需要修改也得改代码。可以放在db.properties配置文件,也是解耦的一种表现。
作业:
- 使用UserDao来解耦之前JAVAWEB代码,模仿TopicDao。
—************
首先是熟练操作IDEA,创建WEB项目,使用tomcat,配置、部署运行等。
复习:
面向对象的目标:高内聚、低耦合、高复用
原来JAVAWEB项目存在高耦合的情况,我们要解耦,我们使用的接口对象的setter()方法进行解耦操作。
4.解耦方式二
程序的耦合
耦合:程序间的依赖关系,包括:
a.类之间的关系
b.方法间的关系
解耦:降低程序间的依赖关系
为bug生,为bug死,为bug奋斗终生
为解耦生,为解耦死,为解耦奋斗终生–》只要项目你不断完善,就存在类、方发、模块、项目之间的耦合度。
实际开发中:
应该做到,编译时不依赖,运行时依赖
解耦的思路:
第一步:使用反射来创建对象,而避免使用new关键字。Class.forName("")
第二步:通过读取配置文件来获取要创建的对象全限定类名。xxx.properties/xxx.xml文件
使用xml文件的解耦,这个将来和spring框架会联系起来,将我们的技术串起来。以听为主,不用记忆。
1.在src下建立beans.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans> <!--beans:指的所有bean的集合,使用xml文件进行解耦--> <!--bean:单个bean的配置文件;id:bean的编号;class:bean路径--> <!--class:mysql下数据库的实现类;给这个类起id名topicDaoMysqlImpl--> <bean id="topicDaoMysqlImpl" class="com.aaa.dao.impl.TopicDaoMysqlImpl"></bean> <!--topicServiceImpl解耦--> <bean id="topicServiceImpl" class="com.aaa.service.impl.TopicServiceImpl"></bean> </beans>
bean:咖啡豆;在java 组件
JAVABEAN:指的就是JAVA里面的可重用组件,玩具:可以由若干零部件组成,组件(组成的零件),在JAVA里面,业务层的接口、接口的实现类、dao层接口、dao层接口的实现类,可以被多次调用(被重用),这些被重用的类、接口都是JAVABEAN。
JAVABEAN的范围远大于实体类,实体类仅仅指的是业务传递数据时的一种重用形态。
2.建立BeanFactory类,操作xml文件
2.1 jar包准备
IDEA的web-INF创建,lib目录,然后把xml的jar放进去,然后Add as Library
2.2 使用BeanFactory来获取bean
package com.aaa.util; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * Created by 张晨光 on 2020/6/2 15:01 * Bean:重用组件;--》JAVABEAN; * Factory:工厂的意思;BeanFactory:Bean的工厂; * 顾名思义:批量创建Bean;操作beans.xml文件,创建bean */ public class BeanFactory { //定义静态方法根据id来获取Bean对象; public static Object getBean(String id){ //用类加载器解析xml文件 try { SAXReader reader = new SAXReader(); //xml的reader对象 //getClassLoader():类加载器,getResourceAsStream:将资源加载为流; Document document = reader.read(BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml")); //xpath技术获得bean元素;相当于之前js:document.getElementById("id") Element element = (Element) document.selectSingleNode("//bean[@id='"+id+"']"); //拿到class属性里面的值 String value = element.attributeValue("class"); //获得反射对象 System.out.println(value); //通过类的全限定名加载类对象[包名+类名];得到value类的class(TopicDaoMysqlImpl):它的类信息; //是不是可以想到:Class.forName("com.mysql.cj.jdbc.Driver") Class clazz = Class.forName(value); //获得实例 return clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(); } } }
3.测试类
//2.1通过BeanFactory来获取一下; TopicService topicService = (TopicService) BeanFactory.getBean("topicService"); //2.直接调用即可 topicService.deleteTopicById(2);
总结:
1.通过建立配置文件xml解耦
`
3.测试类
//2.1通过BeanFactory来获取一下; TopicService topicService = (TopicService) BeanFactory.getBean("topicService"); //2.直接调用即可 topicService.deleteTopicById(2);
总结:
1.通过建立配置文件xml解耦
2.建立BeanFactory解析xml文件,使用反射机制来读取类信息,创建类实例,实现自动创建对象的操作。