0.说明本教程是记录春哥在B站的笔记,想看视频的朋友可以去看看。1.课程框架2.EJB框架Spring框架是为了解决javaEE规范中EJB框架的缺陷而衍生出来的,那么EJB有哪些缺陷呢?首先,EJB的全称是EnterpriseJavaBean。它的缺点是,第一,运行环境恶劣;第二,代码可移植性差。为什么运行环境恶劣?首先,2002年左右的服务器有weblogic、websphere之类的应用服务器(ApplicationServer)。都是收费的,这些容器的复杂度比Tomcat大。只有实现了WebLogic的指定接口才能进行部署,如果想把部署在weblogic中的代码转移到websphere中是行不通的。都说它的代码可移植性差;对了,EJB框架的代码必须部署在EJB容器中,然后将EJB容器部署到对应的applicationServer服务器上才能部署成功;Spring则不同,它部署在tomcat上,而tomcat作为web服务器。其复杂度远不及上述两种容器。Spring的代码灵活性比较强,可以灵活扩展其他不同的框架,可以部署在不同的web服务器上。3.什么是春天?Spring是一个轻量级的javaEE解决方案,它与许多设计模式高度集成。轻量级1>对运行环境没有额外要求,可以运行在以下任何一个开源服务器上:tomcat,resion,jetty:weblogic,websphere2>代码可移植性高,不需要实现额外的接口javaEE方案我们说认为javaEE的开发是分层运行的,主要分为Controller、Service、DAO、DB,而Struts2只能解决Controller层的问题。Mybaits只能解决DAO层的问题,而Spring不一样。它更像是一个胶水框架,每一层都有很好的封装。下面是对应的解决关系SpringMVC---》ControllerAOP---》ServiceJDBC、Hibernate---》DAO集成了众多的设计模式工厂模式代理模式模板模式策略模式4.设计模式4.1什么是设计模式1.广义视角:面向对象设计中,解决特定问题的经典代码2.狭义视角:GOF4人多年前的一本书中列出的23种设计模式,但并不是所有的设计模式都会参与一个项目,毕竟有些只是在桌面开发中用到;4.2工厂设计模式4.2.1什么是工厂设计模式前言:之所以使用工厂设计模式,是因为工厂模式可以很好的解决代码耦合问题。概念:通过工厂类创建对象。好处:解耦什么是耦合:指的是代码之间的强关联。一方的变化会影响另一方。我们知道每次release真的很Heavy,所以我们希望找到一个更通用和灵活的代码,即使有一个变化,也尽可能不影响之前的调用耦合示例:硬编码接口的实现类在程序,例如:publicClassHelloController{(interface)UserServiceuserService=(implementationclass)newUserServiceImpl();}如果实现类发生变化,那么对HelloController整个方法的调用就会发生变化,这就涉及到代码4.2的变化。2如何使用工厂模式4.2.2.1实现一个简单的工厂模式/*那么既然上面代码中产生了耦合,那么最简单直接的解耦方式是什么呢?我们定义一个类返回对应的实现类,然后在controller方法中实现解耦,如下1.定义一个工厂类*/publicclassBeanFactory{//直接返回接口//下面这里使用工厂方法,但是这里有耦合,那么这里的耦合怎么处理呢?publicstaticHelloSevicegetService(){返回新的HelloSeviceImpl();}}//2。在Controller层,通过工厂类返回实现类@PostMapping("factorySolve")publicvoidfactoryTest02(){HelloSeviceservice=BeanFactory.getService();service.login("保罗","123");用户用户=新User("小明","456");service.register(user);}4.2.2.2上述代码问题及解耦改进在进入改进正题之前,我们先来回顾一下创建对象的方法。1>直接调用构造函数创建对象,如UserServiceuserService=newUserServiceImpl();这样创建这个对象的代码就写死了,以后要换别的实现类就不行了。这种方式很明显不利于解耦记住:接口的存在本来就是为了解耦,尽量利用它的特性2>通过反射获取对应的类对象,然后创建对象如:Classclazz=Class.forName("类的完全限定名");UserServiceuserService=(UserService)clazz.newInstance();如果使用这种方法,可以说我要换成另一个实现类,只需要改全限定名即可,但是还是会有一点耦合,就是类的全限定名也硬-coded上了代码,那么怎么优化呢?没错,就是写配置文件!4.2.2.3进入第一步改造:先创建配置文件第二步改造工厂类//为了避免频繁io,我们使用static修饰实现一次性加载privatestaticPropertiesenv=newProperties();static{try{//获取io流对象(其实任何流都可以通过class对象获取io流),但是注意String,Integer好像不可用InputStreaminputStream=BeanFactory.class.getResourceAsStream("/application.properties");//加载到env对象中,此时实现是将类似map结构的数据存储在env对象中env.load(inputStream);//关闭stream对象,否则这个stream的connection会一直存在,最终会导致io重载inputStream.close();}赶上(IOExceptione){e.printStackTrace();}}//下面是修改后的工厂类publicstaticHelloSevicegetServiceUpdate(){HelloSevicesevice=null;//通过反射获取Class对象Classclazz;try{clazz=Class.forName(env.getProperty("userService"));//类服务的全限定名=(HelloSevice)clazz.newInstance();}catch(ClassNotFoundExceptione){e.printStackTrace();}catch(IllegalAccessExceptione){e.printStackTrace();}catch(InstantiationExceptione){e.printStackTrace();}returnservice;}备注:通过上面的修改,如果我们下次要换成别的实现类,只需要改配置文件的全限定名即可,同样,我们也可以使用DAO层的dao代码实现Service的解耦。Class我们通过反射+配置文件获取对应的对象,对于Dao实现类我们通过反射+配置文件获取对应的对象,那么如果有很多其他不同接口的实现类进行解耦,是不是要写一个很多重复的代码以同样的方式?那么,我们需要重构它们,那么它们有什么共同点呢?其实是有的,你看到所有的对象都是通过反射得到的吗?是不是都传入一个“身份”来动态获取实现类?所以我们完全可以对它们进行改造,比如下面的代码publicclassBeanFactory(){//对于工厂方法的改造,我们把这个方法称为通用工厂方法//我们发现上面的代码也有很多冗余,所以我们需要进一步解耦publicstaticObjectgetBean(Stringname){//通过传入标识Objectret=null;尝试{Classclazz=Class.forName(env.getProperty(name));ret=clazz.newInstance();}catch(IllegalAccessExceptione){e.printStackTrace();}catch(InstantiationExceptione){e.printStackTrace();}catch(ClassNotFoundExceptione){e.printStackTrace();返回ret;class),也就是说我们需要创建一个目标类2>通过配置文件的配置通知工厂(application.properties)并在配置文件中以key=value的形式声明3>得到通过工厂类的对象(注意转换)Objectret=BeanFactory.getBean("key");4.4小结上面说了这么多关于工厂设计模式,其实就是想说明一个事实,Spring的本质就是工厂,只是它的功能比我们的demo更强大它的工厂类叫做ApplicationContext,它的配置文件是applicationContext.xml
