SSM框架之--spring(一)

一、why–为什么用spring?

1.spring框架为我们提供了很多现成的功能(IoC、AOP、声明式事务等、SpringMVC等),这些功能可以直接拿来用、提高开发效率。 
2.进一步提高软件产品的质量 
框架是前人对软件开发经验的总结,相当于站在巨人的肩膀上,让一个普通的程序员也能写出高质量的软件成品(符合软件工程的规范,例如高内聚 低耦合、OCP等)

不用框架 做小的项目没问题,但是做大的项目就需要框架做强大的支撑,这一点从MyBatis就可以看出来,如果不用MyBatis,用JDBC做项目太繁琐了。

二、what–spring是什么?

Spring 春天 心情好了 软件质量高了 工资高了 需求变了 不需要改代码 不需要加班了

MyBatis、Hibernate 优秀的持久化层解决方案 当今主流的ORMapping工具

SpringMVC、Struts MVC框架 代替servlet

Spring 综合型框架(一站式服务) 管理层框架

综合型框架(功能很多 涉及到Java EE各层)

管理层框架(javaEE各层 po dao service action 大家长 不管你 软件质量得不到保证)

从spring的四个大的方面讲解一下spring 
这里写图片描述

1.IOC容器

Inversion Of Control 控制反转

2.对持久层支持(DAO ORM)

简化hibernate开发(简化jdbc开发)
声明式事务
  • 1
  • 2
  • 3

3.web层集成(控制器 jsp)

自己的MVC框架 spring mvc

整合web层框架 struts1 、struts2、WebWork、JSF等

4.AOP

Aspect Oriented Programming 面向切面编程

切面说白了就是一个类 可以给任何方法前面或后面加方法 拦截器就是一个切面 思想就是AOP思想

5.JEE支持

JMS即Java消息服务(Java Message Service)

JCA (J2EE 连接器架构,Java Connector Architecture): 用来连接非java语言编写的系统.

Remoting 远程方法调用

EJBs 企业级javaBean 处理分布式业务

Email 邮件

JMX(Java Management Extensions,即Java管理扩展)

三、IOC容器(核心功能)

IOC Inversion Of Control 控制反转

什么是容器

1.集合 list

2.tomcat jsp/servlet容器 只管理jsp servlet对象生命周期(从创建到销毁)

3.spring IOC容器能管理所有对象的周期(从创建到销毁 对象的存取)

为什么要使用IOC容器(IOC容器的好处)

1.解耦 (彻底实现OCP) 
2.Inversion Of Control 控制反转 
3.单例

1.IOC容器的好处之解耦(彻底实现OCP)

解耦(使用接口) 紧密耦合(笔记本和屏幕)——->松散耦合(PC)

紧耦合坏处:需求变了 需要改代码

演示笔记本运行例子(相当于自己实现spring的IOC功能)

import java.io.BufferedReader; 
import java.io.FileReader;

public class Test { 
public static void main(String[] args) throws Exception{

    //从文件中读进来
    //1.建立通道
    FileReader fr = new FileReader("c:\\spring.txt");

    BufferedReader br = new BufferedReader(fr);

    String screenClassName = br.readLine();

    //Screen screen = new RetinaScreen14();

    Class<?> clazz = Class.forName(screenClassName);
    Screen screen = (Screen)clazz.newInstance();

    //改成反射的
    Notebook notebook = new Notebook();
    notebook.setScreen(screen);

    notebook.work();
}   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

}

为了让笔记本和具体的屏幕类解耦,不依赖于具体的屏幕类,紧耦合–>松散耦合,提高软件质量,不用改代码,可维护,要写这么多代码,这么麻烦???

我也不会怎么办???

使用spring啊

四、如何使用spring?

http://maven.springframework.org/release/org/springframework/spring/

Spring3.2.4

1.导jar包

spring-core-3.2.4.RELEASE.jar 
spring-beans-3.2.4.RELEASE.jar 
spring-context-3.2.4.RELEASE.jar 
spring-expression-3.2.4.RELEASE.jar

commons-logging-1.1.1.jar spring依赖于这个日志包

注:老版本的spring有一个整合包spring.jar,也有分开的,新版的没有整合包,都是分开的,分开的目的是便于按需引入.

2.定义类和接口

public interface IScreen { 
public void display(); 
}

public class Screen14 implements IScreen{

public Screen14(){
    System.out.println("创建了Screen14对象");
}

public void display(){
    System.out.println("使用14寸屏幕进行显示");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

}

public class RetinaScreen14 implements IScreen{

public RetinaScreen14(){
    System.out.println("创建了RetinaScreen14对象");
}

public void display(){
    System.out.println("使用14寸高分屏显示");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

}

public class Notebook {

private String pinpai;

private IScreen screen;

public Notebook(){
    System.out.println("创建了Notebook对象");
}

public void setScreen(IScreen screen){
    System.out.println("调用了setScreen方法  设置屏幕");
    this.screen = screen;
}


public String getPinpai() {
    return pinpai;
}


public void setPinpai(String pinpai) {
    System.out.println("调用setPinpai 设置品牌");
    this.pinpai = pinpai;
}

public IScreen getScreen() {
    return screen;
}

public void work(){

    screen.display();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

}

3.配置文件

applicationContext.xml java工程放到src下 相当于classes (Web工程稍后再说)

宁波整形医院http://www.zuanno.com/
宁波好的整形医院http://www.zuanno.com/

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">


    <!-- 使用反射创建对象 -->
    <!--Screen14 screen14 = new Screen14();-->
    <bean id="screen14" class="com.test.Screen14"/>


    <!--Notebook notebook = new Notebook();-->
    <bean id="notebook" class="com.test.Notebook">
        <!-- 
            notebook.setPinpai("联想");
            notebook.setScreen(screen14);
         -->
        <property name="pinpai" value="联想"/>
        <property name="screen" ref="screen14"/>
    </bean>
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

4.测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    public static void main(String[] args) {

        //获得spring IOC容器
        //创建对象、设置依赖关系
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //从容器中取id为notebook的对象
        Notebook notebook = (Notebook)context.getBean("notebook");

        notebook.work();
    } 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

IOC控制反转

Inversion of Control 控制翻转 
控制权的反转 什么控制权?

主要体现在两点上

1.创建对象的控制权

由程序员 反转给了spring完成 
2.设置依赖关系的控制权利(重点)

本来是程序员 notebook.setScreen(screen14);

现在交给了spring完成

好处: 
1.不用new 和 set了省事了(框架帮你完成了)

2.解耦(彻底实现OCP)

3.符合现实生活:

现实生活中来说用户想使用笔记本,只要打开笔记本就可以了,没必要先自己造一个笔记本,再造个屏幕,组装起来?这样用户不是累死了?(关注的太多) 
用户只要关注具体的业务逻辑(让笔记本工作)就可以了,其他的都交给spring来替 
你完成(相当于笔记本是用来从spring工厂买过来的)。这样用户就从非业务逻辑(创建对象、设置依赖关系)的代码中解脱出来。

DI:Denpendency Injection 依赖注入

控制反转这个名词不太形象,所以spring又换了一种更加形象的解释,叫DI,其实是一个思想,只是DI更好理解罢了。

依赖注入

依赖关系,是spring给你注入的(设置的)

笔记本依赖于哪个屏幕类的对象 是spring帮你完成的,spring相当于对象的粘合剂

依赖注入的两种方式:

一、setter注入 (推荐使用)

使用set方法给笔记本的屏幕初始化,告诉笔记本运行时到底依赖于哪个屏幕 Screen14 还是 RetinaScreen14

两步 
1.给笔记本的屏幕属性 添加setter方法

public class Notebook{

private Screen screen;


public void setScreen(Screen screen){
    System.out.println("使用setScreen方法把屏幕组装到笔记本中");
    this.screen = screen;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

}

2.修改applicationContext.xml

    <bean id="screen14" class="com.test.Screen14"/>

    <bean id="retinaScreen14" class="com.test.RetinaScreen14"/>

    <bean id="notebook" class="com.test.Notebook">

        <!-- setter注入  notebook.setScreen(retinaScreen14)-- >
        <property name="screen" ref="retinaScreen14"/>
    </bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

类的属性是 基本类型和String 使用value

类的属性是引用类型 使用ref reference 引用

注入集合的情况自己看 注入的两种方式.txt

二.构造器注入

使用构造函数给 笔记本的屏幕进行初始化,设置笔记本和屏幕的依赖关系。

  1. 定义Notebook 
    package com.ioc;

public class Notebook {

private String pinPai;
private Screen screen;

public Notebook() {
    System.out.println("创建了Notebook对象");
}


public Notebook(String pinPai, Screen screen) {
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

System.out.println(“使用两个参数的构造函数(String pinPai, Screen screen)创建Notebook对象”); 
this.pinPai = pinPai; 
this.screen = screen; 
}

public void work(){
    screen.display();
}
  • 1
  • 2
  • 3
  • 4

}

2.给笔记本添加相应的构造器

public Notebook(String pinPai, Screen screen) {
  • 1
  • 2

System.out.println(“使用两个参数的构造函数(String pinPai, Screen screen)创建Notebook对象”); 
this.pinPai = pinPai; 
this.screen = screen; 
}

3修改applicationContext.xml

<bean id="screen14" class="com.ioc.Screen14"/>

<bean id="retinaScreen14" class="com.ioc.RetinaScreen14"/>

 <!--Notebook notebook = new Notebook(“IBM”,retinaScreen14)-->
<bean id="notebook" class="com.ioc.Notebook">
    <constructor-arg value="IBM"/>
    <constructor-arg ref="retinaScreen14"/>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果有两个同类型的参数,例如两个String类型的参数,spring框架会按照构造函数中的顺序设置,可以给电脑加一个productNo产品编号 属性演示

public Notebook(String productNo, String pinPai, Screen screen) { 
System.out.println(“使用3个参数的构造函数创建Notebook对象”); 
this.productNo = productNo; 
this.pinPai = pinPai; 
this.screen = screen; 
}


<bean id="notebook" class="com.ioc.Notebook">
        <constructor-arg value="1"/>
        <constructor-arg value="IBM"/>
        <constructor-arg ref="retinaScreen14"/>
    </bean>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

控制台打印

如果把配置文件中的constructor调换顺序

<bean id="notebook" class="com.ioc.Notebook">
        <constructor-arg value="IBM"/>
        <constructor-arg value="1"/>
        <constructor-arg ref="retinaScreen14"/>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5

可以通过设置index值标示给第几个参数传值,index=0表示给构造函数中的第一个参数传参,index=1表示给第二个参数传参.如果不写index,默认第一个参数index=0,依次类推

配置文件如下

<bean id="screen14" class="com.ioc.Screen14"/>

    <bean id="retinaScreen14" class="com.ioc.RetinaScreen14"/>

    <bean id="notebook" class="com.ioc.Notebook">
        <constructor-arg value="IBM" index="1"/>
        <constructor-arg value="1" index="0"/>
        <constructor-arg ref="retinaScreen14" index="2"/>
    </bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

IOC容器的好处 之 单例


  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("*********************************");    
  Notebook notebook = (Notebook)context.getBean("notebook");
  Notebook notebook2 = (Notebook)context.getBean("notebook");

  System.out.println(notebook==notebook2);//true 证明两次获得的是同一个对象
  notebook.work();


注意:两次得到的是一个对象 getBean方法只是在容器里取出一开始创建的对象而已,并没有创建对象,创建对象由第一句完成

如果想每次都创建一个新的对象,怎么办??


<bean id="notebook" class="com.ioc.Notebook" scope="prototype">
        <constructor-arg value="1"/>
        <constructor-arg value="IBM"/>
        <constructor-arg ref="retinaScreen14"/>
</bean>

一句话总结
IOC容器除了是一个普通容器外,主要解决了统一管理对象生命周期、解耦合、维护依赖关系,以及应用程序对单例的大量需要等问题。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

五.自动装配和依赖检查

自动装配:就是程序员不用显示的使用 给笔记本设置一个屏幕,设置屏幕的 
工作交给spring自动完成就可以了,只需要在需要使用自动装配功能的 节点上加入 autowire属性即可

autoware:no(默认值) 不自动装配 
autoware:byType 按照类型自动装配,spring正好找到一个就装配,如果找到两个或两个以上类型相同的,就报错.没有找到就不装配 
autoware:byName 按照名字自动装配

也可以定义到beans节点上 
这样所有的bean都是按名称自动装配了

虽然说自动装配它减少了配置文件的工作量,但是程序员不知道到底装配了什么,降低了依赖关系的清晰性,所以不推荐使用

依赖检查:spring框架帮你检查bean的属性是否都初始化

dependency-check=”default/none/simple/objects/all”

default 表示继承beans的,父节点beans的默认值none 不检查

simple类型:检查基本类型、包装类型和String、集合有没有初始化,没初始化就报错

objects: 只检查引用类型有没有初始化

All: 基本类型和引用类型都帮你检查一下有没有初始化

注意:依赖检查的时候要为需要检查的属性设置setters方法 否则即使在配置文件中配置了依赖检查,spring也不会帮你进行依赖检查

六、在web应用程序中使用spring

如果想把spring用在web应用程序上,只需要修改三步

1.把applicationContext.xml放到WEB-INF下

2.另外导入一个jar包spring-web-3.2.4.RELEASE.jar

3.在web.xml中配置一个监听器 ContextLoaderListener

<listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

public class ContextLoaderListener extends ContextLoader implements ServletContextListener

配置完毕后启动tomcat

控制台显示 
创建了RetinaScreen14对象 
创建了一个Screen14的对象 
创建了一个Notebook对象 
使用setScreen方法 把屏幕装到笔记本里

相当于服务器一启动 
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”); 
执行了

启动时ContextLoaderListener 读取applicationContext.xml 创建了对象 并设置好对象之间的依赖关系

注意: 
如果把文件放到WEB-INF下,使用下面语句就无法找到applicationContext.xml了,因为这句话是从src下找

ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);

这样如果想测试程序,读取WEB-INF下的applicationContext.xml就必须启动web应用,比较麻烦,为了方便测试

可以使用

ApplicationContext context = new FileSystemXmlApplicationContext(“WebRoot/WEB-INF/applicationContext.xml”);

这样就可以在Test测试类中运行程序了,而不需要启动web应用

没有更多推荐了,返回首页