初入Spring

2018年春天,我开始学Spring了,目标是在暑假时能找一个实习工作(不知道有没有人要)。路要一步一步走,知识要一点一点学,虽然我很急切,但是没办法。一口吃不了个胖子。

首先在之前,学习了Servlet+JSP+JavaBean的小Demo。当客户端向服务器发出请求是,服务器把得到的请求发送给控制器Servlet,而在Servlet中需要创建Service对象来调用业务层相关功能(所以说控制器层Servlet依赖于业务层Service)而在Service中又需要创建数据库层DAO对象来对数据库进行操作(故说业务层Service依赖于数据库层DAO)

针对上述过程,我们需要考虑这样几个问题。1.Servlet,Service以及DAO对象的创建时间,创建数量。2,Servlet,Service以及Dao之间的依赖关系。如何处理这些问题呢?Spring就是用来处理对象的创建,以及对象之间依赖关系的一个开发框架。它打破了我们传统开发的观念,我们不再需要像以前那样在具体的类中创建具体的对象,而是将对象的创建交给它去完成,他是我们所要学习的框架中最重要的框架。

1.Spring框架中的专业术语

1.1组件/框架设计

1.侵入式设计:对现有类的结构有影响,即需要实现或继承某些特定类。如Struts框架。

2.非侵入式设计:引入了框架,对现有结构没有影响,如Spring框架,Hibernate框架

1.2控制反转

Inversion On Control,简称IOC。对象的创建交给外部容器自动完成,这个就叫做控制反转(有控制反转就有控制正转,控制正转:对象的创建由我们自己创建)

依赖注入:dependency Injection 简称DI。用于处理对象间的依赖关系。

二者区别:控制反转用来解决对象创建问题(对象的创建不需要我们手动创建,而是交给框架去完成)

依赖注入在创建完对象后,对象的关系处理就是依赖注入。(通过set方法依赖注入。也可以理解为另一种对象之间的耦合方式)

1.3 AOP

面向切面编程。切面,简单来说可以理解为一个雷。由很多重复代码形成的类。切面举例:事务,日志,权限。关于AOP的详细讲解会在明天的博文中总结。

2.Spring框架概述

Spring 框架,可以解决对象创建以及对象之间依赖关系的一种框架。且可以和其他框架爱一起使用。例如ssh

一方面可以与structs整合,让struts的action创建交给spring。SpringMVC模式,用springmvc整合了就不用sturts了。

另一方面,可以与hibernate整合可以使用Spring对hibernate操作的封装。这可以用mybatis代替。现在常用ssm框架。

Spring提供了一站式解决问题的方案。可以完美替代前面的Servlet,Service,Dao。

1)SpringCore:Spring的核心功能,包括IOC容器,解决对象创建以及依赖关系

2)SpringWeb: Spring对外部模块的支持。

3)SpringDao :Spring对jdbc操作的支持。

4)SpringORM:Spring对ORM的支持。

5)Spring AOP:关于AOP的详细下一篇吧

6)SpringEE:Spring对javaEE其他模块的支持。

3.Spring开发步骤

1)导入jar包。

可以参考一张图。

红框框标出来的部分是比较重要的。


除了常用的Spring包外,这里面还有个日志包。

写在前面的话:当你运行程序出现org.springframework.beans.factory.BeanDefinitionStoreException的报错信息时,不要想了,出现这种报错的信息原因绝对是因为jdk版本和你导入的spring jar包不兼容的问题。由于spring3.x与jdk1.7兼容,而spring4.x与jdk1.8兼容,所以这里提供两种解决方案:

  • 1.将jdk版本调为1.7,我用的开发工具为IDEA,它默认下的JDK使用1.8版本,所以我需要在三个地方将jdk的版本改过来(前提是你已经下载了jdk1.7版本),修改IDEA配置中Project的jdk版本、Modules的jdk版本、SDKs的版本,如果你用到leTomcat还需要修改Tomcat配置的jdk版本。这样jdk1.7与spring3.x才兼容。
  • 2.将spring3.x.jar换成spring4.x.jar包。这种方式比较繁琐,建议大家使用第一种方式。spring4.x与jdk1.8才兼容。
2)配置核心文件applicationContext.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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
3)使用

首先我们创建一个pojo(POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称)对象User.java


然后创建测试类。使用这个User对象。以前我们要使用User对象时,直接User user=new User(); new 一个对象即可。

而当我们使用Spring后,就应该这样使用User对象,首先在applicationContext.xml中添加<bean>标签,一个<bean>标签代表一个pojo对象:


其中各个属性的说明见注释。然后我们通过如下步骤获取pojo对象


运行测试类:


说明成功获取到User对象,上述是通过工厂类获取的IOC容器创建的User对象,下面我们看看使用Spring框架获取pojo对象的第二种方式直接得到IOC容器的对象。


虽然我常用第二种方式。

4.<bean>创建的细节

对上述代码进行改进,对于IOC容器对象,我们只需要创建一次即可。所以将创建IOC对象的代码改为成员变量。


得到结果:


发现答应的这两个User对象id都一样,说明我们获取到的是同一个对象,也说明通过<bean>标签设置的pojo对象是单例的。为什么呢?其实<bean>标签默认有一个scope="singleton"的属性,代表该<bean标签对象的pojo对象是单例的。我们可以将该属性值改为scope="prototype",如下:


再次运行可以得到


说明此时获取的两个User不再是同一个对象。

总结:在<bean>标签中设置bean对象为单例时,该对象在系统启动时就会创建;设置为多例时,该对象在我们需要使用时才创建。

5.SpringIOC容器

SpringIOC容器,是Spring的核心内容,用于创建和处理对象间的依赖关系。

5.1对象的创建

利用IOC容器创建对象的方式有如下几种:1.调用午餐构造函数。2.调用带参构造器。3.工厂创建对象。包括工厂类的静态方法创建对象和工厂类的非静态方法创建对象。4.反射(IOC的原理就是通过反射来创建对象)

5.1.1调用无参构造器

在配置文件中加入如下内容


5.1.2调用带参数构造器


<constructor-arg>标签中还有一个ref的属性,属性值代表引用配置文件(即IOC容器)中的相应对象。

故还可以采用这种方法调用带参数构造器创建对象:


5.1.3工厂创建对象

首先创建一个工厂类:


调用工厂的实例方法创建对象:


调用工厂静态方法创建对象:


5.2处理对象的依赖关系

在IOC容器的配置文件中我们有如下给对象注入属性的方法:1.通过构造方法。2.通过set方法给属性注入值。3.p名称空间。4.自动装配。5.注解。

5.2.1通过构造方法

首先我们来看看如何通过构造方法来给对象的属性赋值,在配置文件中添加如下标签即可通过构造器给该User对象的属性赋值。


5.2.2通过set方法

通过set方法给属性赋值,前提是在User对象中给它的属性添加了set方法:


接下来的案例中,我们以前用的service,servlet,dao会根据MVC模式进行相应的修改。




都需要我们自己在.java文件中自己添加A a=new A(); 来创建其所需要的依赖对象,而现在我们就将对象的创建交给IOC了,选择set给属性赋值的方式来给他们注入其所依赖对象,修改他们的代码。



然后我们需要在application.xml中进行配置


ref的属性值代表给该对象注入它所以来的对象,即我们上述讲到的依赖注入,通过上述步骤我们便完成了将对象的创建交给IOC的操作。

上述三个对象的创建我们需要写三个<bean>标签才能完成,接下来我将介绍第二种方法通过内部bean的操作一次性完成它们的创建以及它们之间的依赖关系,修改配置文件中的内容:


通过上述内部<bean>标签的方式我们便可实现和set注入依赖相同的效果。我们来看看它们两者的相同和区别:

  • 相同:都可以创建Service对象,并处理了之间的依赖关系。
  • 区别:set注入创建的Service对象可以给另一个Servlet对象调用,而内部bean将Service对象写在Servlet内部导致该Service对象只能被该Servlet使用,所以内部bean标签的使用场景在只需要一个Servlet对象的项目中。

5.2.3自动装配

当我们在配置文件中用<bean>标签指明相应对象的同时就将这个对象放入到了IOC容器中(其中标签中的id属性唯一指示一个对象),当我们给该bean标签添加了autowrite="byName"的属性后,对于该标签对应的对象注入的属性,会去IOC容器中自动查找与属性同名的对象。


通过上述三个<bean>标签,我们就将userDao,userService,userServlet三个对象添加到了IOC容器中,我们在UserService对象的bean标签中加上了autowrite=“byName”的属性,这样我们查看UserService.java的代码,它有一个UserDao对象名为userDao的属性,此时就会自动去IOC容器中去寻找与userDao同名的对象(即在bean标签中寻找id为userDao的对象)然后进行诸如,此时我们若将<bean id="userDao">的id=“userDao”属性值改为userDao1或者其他名字,则系统会出现空指针异常。

我们也可以将该属性定义到全局<beans>标签中,设置default-autowrite="byName"的属性,这样就不用每个bean标签中都写上autowrite="byName"属性了。利用自动装配的优缺点:简化了配置,但不利用系统维护。所以一般不推荐此用法,下面我们再来介绍第5中非常简单的配置。

5.2.4 注解

注解方式简化了Spring的IOC容器的配置。

使用步骤:1.先引入context名称空间。2.开启注解扫描。3.使用注解,通过注解的方式,把对象加入到IOC容器中。

首先在IOC配置文件中引入context名称空间,即在<beans>全局标签中添加 

xmlns:context="http://www.springframework.org/schema/context"

属性。然后在配置文件中添加如下标签。

<context:component-scan base-package="pojo"/>

base-package 表示该扫描器只扫描此包下所有类

最后我们便可以使用注解了,在pojo对象的.java文件中分别加入如下注解:



@component注解:代表将该对象放入到IOC容器中,括号里面的名字代表该对象在IOC容器中唯一标识的名字,该注解卸载代码第一行。

@Resource注解:用于将该对象依赖的属性从IOC容器中找到并注入,括号里面的name属性值必须跟@Compenent注解里填入的名字相同。

通过注解方法便可去掉各.java文件中为属性创建设置的set方法。

继续对上述注解方式进行配置优化,去掉括号中的内容:




在测试类中运行依然可以正常运行。

说明利用@Compenent注解的方式是通用的将对象加入到IOC容器中的方式,而有时候我们需要区别各层对象添加的方式,所以这里我们将Dao层对象添加到IOC容器的注解方式改为:@Repository表示持久层的组件;修改Service层对象添加到IOC容器的注解方式:@Service表示业务逻辑层的组件;修改Servlet层对象添加到IOC容器的注解方式为:@controller表示控制层的组件。其实功能都一样,只不过为了我们更好地区分。

另外需要说明的是使用注解的当时将对象添加到IOC容器中和在xml文件中添加配置的方式是可以共存的。但通过@Resource不带括号的注解,必须要保证该类型只有一个变量,所以一般情况下我们还是优先使用@Resource(name=“”)注解


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值