Spring是目前使用最广泛的经典轻量级Java web开发开源框架。它是分层框架,允许使用者使用任意组件,目前在web项目中一般经典分法分三层:web层,service层,dao层,(这就是所谓的分层开发模式,将程序的运行人为分成层,方便解耦,方便多人并行开发,当然分成多少层并没有严格限制),Spring在这三层都有解决方案,也就是它不是一个整体,它将每层的解决方法单独做成了一个组件,你可以单独使用。下面是Spring这个框架的所有组件组成:

建议自己可以手画一下,还是比较重要的。整个框架中,红色字体部分,Core Container是最重要的,只要使用Spring框架,就一定要用到它们,是必须要使用的。其中core模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能;beans 模块提供 BeanFactory;context模块是在core和 beans 模块的基础上建立起来的,继承自Bean模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过Servelet容器)等功能,ApplicationContext接口是Context模块的焦点。spring-context-support提供了对第三方库集成到Spring上下文的支持,expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。
除了核心模块其他模块都是可选择的,比如在Data Access模块,我们选择使用了MyBatis框架,那就不会用到这里的模块;在Web模块中,我们选择了MVC,这个在SpringMVC中会单独讲。其中AOP和Aspects也可说一下,因为只要使用Spring框架我们都会使用切面编程,对项目进行分层,而AOP 模块提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦;spects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。说完这个我们基本上也就能明白今天的学习我们要用到哪些jar包了。

可以看到使用Spring需要导入四个核心jar包,另外由于core依赖commons-logging这个包,所以共需要5个jar包。
一、核心:Spring的IoC(控制反转)
1、IoC概念 :控制反转的含义就是原来我们在Java开发的时候,如果要使用某一个类的对象,我们需要对其进行实例化,比如通过new的方式,在Spring里面这个过程交给了IoC容器,只要我们在xml文件中配置好bean工厂,加载配置文件后它会自动帮我们创建好这个对象,然后通过核心接口获取这个对象;这是一个对象的时候,如果有两个对象,其中一个对象A依赖另一对象B,也就是说A中使用了B对象,这个时候我们可以普通的方式在A对象中new一个B对象,也可通过上面所说的控制反转创建一个对象,但是Spring提供了一个更简单的方式,叫做依赖注入(它也是一种控制反转),配置好配置文件xml后,我们可以将B对象作为一个普通数据类型在A类中声明,并且可以使用setter方法给其传入数据,然后直接在A对象中使用它的方法和属性。
首先我们先创建一个接口Article,然后它的实现类ArticleImp(这里我们也可以直接创建实现类是没有问题的,由于我们以后都会采用接口编程,所以最后还是接口和实现类一起创建);
其次,我们还要测试DI,所以我们还创建一对接口和实现类,ArticleList和ArticleListImp,这个类是依赖ArticleImp这个类的。




2、IoC(控制反转)的实现
对于上面的两个实现类ArticleImp和ArticleListImp,我们均可以使用IoC来实现对象创建,那么我们就拿ArticleImp来举例吧。实现控制反转的第一步是先要配置xml文件:

配置完毕,我们就可以创建一个测试Java文件,获取这个对象并使用其中的方法看看效果,我们还可以与普通的new出来的对象的操作做一个对比:

3、DI (依赖注入)的实现,下面来介绍第二种控制反转,准确的说在ArticleListImp对象依赖ArticleImp那部分使用了依赖注入,在获取ArticleListImp对象还是使用了控制反转,首先还是配置文件,这个配置文件既需要配置两个对象的控制反转信息,还需要配置依赖对象中被依赖对象的信息:

第二步就还是一样了,加载文件创建对象,然后获取对象。

运行如果没有配置测试模块,可以使用coverage as,结果如下:

上述案例是我们随便创建两个对象,然后让其中一个依赖另外一个,来测试。那么在实际的项目过程三层架构中,Service层一定会依赖Dao层,因为业务逻辑肯定需要接收数据层传来的数据,所以一般都会采取这种流程:Dao层和Service层分别通过IoC获取到了类的实例,然后通依赖注入将Dao实例(包含数据的对象)注入Service实例中,完成了整个web项目数据的流转。
二、关键点,我们发现上述代码有两个关键点,分别是配置文件xml(创建对象或者bean的实例化)和加载文件获取对象的类:
1、配置xml(主要就是各种属性表示的含义作用)
(1)创建对象方式(实例化对象方式):默认构造、静态工厂、实例工厂。
首先,静态工厂实例化必须要有静态工厂类,这是一个生产bean的工厂,其方法都是静态方法,这个主要配置<bean id="" class="bean工厂类" factory-method=“”></bean>,就是这里面的factory-method配置为工厂里面的静态方法;其次实例工厂,也需要创建好实例工厂类,里面的方法是实例方法,这个配置有两部分,先要普通方式将工厂类配置出来,<bean id="" class="bean工厂类" ></bean>,然后配置工厂里面的方法,<bean id="" factory-bean=“上面的工厂bean的id值” factory-method=“实例方法” ></bean>。
(2)作用域:其在bean中配置,属性名scope,值有五个,分别为singleton、prototype、request、session和global session。为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype(这是默认值)。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。
(3)生命周期:一共十一步。只说其中的三个步骤,在开发中会用到的,初始化和销毁bean以及后处理bean。
a、<bean id="" class="" init-method=“配置初始化方法” destroy-method=“配置销毁方法”></bean>,如果这个时候再调用该对象的方法,就会自动在之前执行初始化方法(一般会放准备数据),如果最后通过ApplicationContext.close()关闭IoC容器,就会自动执行销毁方法(一般放清理资源的方法)。
b、BeanPostProcessor(后处理Bean),这个接口有两个方法,分别在初始化前和初始化后执行,从而产生了代理对象,这是AOP的底层。
(4)属性注入:一共有四种属性注入的方法(setter方法,p命名空间,SpEL,集合注入),只说setter方法,集合注入。属性注入其实就是对对象中的属性进行赋值。
a、Bean中有setter方法,如下方式配置xml文件,普通数据<bean> <property name=“属性名” value=“属性值” > </property> </bean> 或者<bean> <property name=“属性名” > <value>属性值</value> </property> </bean> ;引用数据:<bean> <property name=“属性名” ref=“引用对象的名字” > </property> </bean> 或者 <bean> <property name=“属性名” > <ref=“引用对象的名字”/> </property> </bean>
b、集合注入,是以后项目中最常见的,项目中数据传递最常见的就是集合形式。包括了String,List,Set,Map,Property,创建一个ArticleImp类,分别创建上面5个属性,创建setter方法和toString方法(方便打印数据)。

主要看如何在配置文件注入属性值。



2、核心API,这个就是IoC的实现类,IoC在具体代码中的表现,这个在后面的web项目的开发中就用不到,因为有框架替我们写好了,可以了解一下。
(1)BeanFactory:生成bean的接口;采用延迟加载,调用getBean方法的时候才开始加载;
(2)ApplicationContext:继承了BeanFactory,也是生成bean的接口,但是功能更强大;
(3)ApplicationContext的两个实现类:ClassPathXmlApplicationContext,用于加载classpath(或者src)下指定的xml文件,这个刚才已经使用过了,getBean()方法就是获取对象的方法,FileSystemXmlApplicationContext用于加载指定盘符下面的xml文件。
所以,BeanFactory、ApplicationContext我们可以称它们为IoC容器,具体的IoC容器。
二、注解,本质上就是一个类,使用方法:@注解名称。其用来取代上面我们学习的xml配置文件中的内容,比xml配置更简单易操作速度快,实际项目中建议采用此种方法来实现Spring。
注解使用时,有一个前提,这个需要在xml文件里面配置,让Spring扫描到文件中的注解。增加的内容如下:
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation= "http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
<context:component-scan base-package="需要扫描的包名" > </context:component-scan>
1、这个时候就可以使用注解了,注解的形式种类很多,介绍如下常用的:
a、@Component 使用这个注解标注哪个类,表示的含义就是xml文件里面的<bean class="">,也可以说该注解取代了xml文件的<bean class="">配置部分;
b、@Component(“id名称”)标注的类就表示<bean id="" class="">;
c、在web项目开发中,由于主流都分了三层来处理,所以分别对这三层使用了不同的注解,就是名称不一样,但是效果和@component是一样的。在web层,使用@Controller;在service层,使用@Service;在dao层,使用@Repository。
上述注解解决了xml文件中处理Bean工厂的配置;那么针对属性注入又是如何处理的呢?
2、属性注入:
普通数据类型:@Value(“需要注入的数据值”)
引用数据类型:方式一:按照类型注入@Autowired,但是这个很少用,不可能将一种类型一个数据注入;方式二:按照名称注入,@Autowired @Qualifier(“名称”),两个注解同时使用可以给具体属性,或者更常用的@Resource(“名称”)

我们这里来做一个思考,其实整个IoC和DI是不是帮我解决了一个问题,就是将POJO也能变成像普通数据类型那样声明和使用setter方法赋值。
三、Spring的AOP(面向切面编程),切面编程就是将我们的项目开发人为分层处理,一般分为三层:Web层,Service层,Dao层
1、原理:通过预编译方式或者运行期动态代理实现程序功能的统一维护的技术。其核心就是动态代理。其采用横向抽取的方式编程,取代了我们之前一直学的纵向继承的方式。通俗来讲,就是之前子类将父类中的方法直接拿来用,代理就是将多个类的方法直接综合起来用,实际项目中,Spring会自动进行代理操作,我们只需要写类,然后配置,Spring会自动综合它们。
target:目标类,需要被代理的类;Joinpoint:连接点,这那些可能被增强(拦截)的方法;PointCut:切入点,已经被增强的方法;advice:通知增强,增强代码;proxy:代理类;Weaving:织入,将增强advice应用到目标对象target中,来创建新的代理对象proxy的过程;aspect:切面,指的是切入点pointcut和通知advice的结合
2、应用:事务管理、性能检测、安全检查等等,我们用到的最多的就是事务管理。为了了解AOP编程的整个流程和发展演变过程,我们从三个阶段来引入AOP:
(1)手动代理:
a、接口+实现类 jdk的动态代理Proxy:其实现方法就是通工厂类将包含增强代码(advice)的切面类织入目标类的过程。其使用的简化“装饰者”设计模式。
b、实现类 字节码增强:使用框架 cjlib。都不需要配置文件。
(2)工厂bean代理(半自动):
半自动方法就是Spring创建代理对象,我们直接从容器中获取对象,因此需要配置IoC。
(3)AOP(全自动):
只需要提供目标类,直接自动就生成代理对象,这个我们一般在框架AspectJ下开发。
3、AOP的框架AspectJ:
切入点表达式和通知类型是该框架的重点。
网友评论