Spring 入门

什么是 Spring ?

Spring 叫做 EE 开发的一站式框架。

  • 一站式框架:有 EE 开发的每一层解决方案。
    • Web 层:SpringMVC
    • Service层:Spring 的 Bean 管理,Spring 的声明式事务
    • Dao层:Spring 的 JDBC 模板,Spring 的 ORM 模块

Spring 入门(IOC)

什么是 IOC?

  • IOC:Inversion of Control(控制反转)
  • 控制反转:将对象的创建权交给 Spring,Spring 会帮你创建这个类的实例对象。

下载 Spring 的开发包

解压开发包

在这里插入图片描述

  • docs:Spring 的开发规范和 API
  • libs:Spring 开发 jar 包和源码
  • schema:Spring 的配置文件的约束

创建一个 web 项目引入 jar 包

创建对应的接口和类

/**
 * 用户管理业务层的接口
 */
public interface UserDao {
    public void save();
}


/**
 * 业务层实现类
 */
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("UserDaoImpl执行了!");
    }
}

public class UserDaoHibernateImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("UserDaoHibernateImpl执行了...");
    }
}

/**
 * Spring入门
 */
public class SpringDemo1 {
    @Test
    /**
     * 传统方式的调用
     * 这里相当于一个业务层,现在是UserDaoImpl类的实现,如果想变成UserHibernateImpl的实现,必须修改
     * 这里的源代码
     */
    public void demo1(){
        UserDao userDao = new UserDaoImpl();
        //UserDao userDaoHibernate = new UserDaoHibernateImpl();
        userDao.save();
    }
}

  • 问题:如果底层的实现切换了,需要修改底层的源代码,能不能不修改底层的源代码对程序进行扩展?
    在这里插入图片描述
    对程序的扩展式开放的,对修改源代码是关闭的。当我们使用面向接口编程的时候还是会修改源代码,所以这个方法也不是最好的。这里我们使用工厂模式开解决这个问题。我们通过建立一个工厂类来管理实现类的创建工作。这样可以把在很多类中要修改的地方,变成只改一个类。最终的目的是为了只更改配置文件而不更改程序的源代码。

将实现类交给Spring管理

<?xml version="1.0" encoding="UTF-8"?>
<!--spring配置文件applicationContext.xml的约束-->
<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.xsd">

    <!--Spring入门配置=================-->
    <bean id="userDao" class="spring.demo1.UserDaoImpl"></bean>
</beans>

编写测试类

/**
 * Spring入门
 */
public class SpringDemo1 {
    @Test
    /**
     * 传统方式的调用
     * 这里相当于一个业务层,现在是UserDaoImpl类的实现,如果想变成UserHibernateImpl的实现,必须修改
     * 这里的源代码
     */
    public void demo1(){
        UserDao userDao = new UserDaoImpl();
        //UserDao userDaoHibernate = new UserDaoHibernateImpl();
        userDao.save();
    }

    @Test
    /**
     * Spring方式的调用
     */
    public void demo2(){
        //创建Spring工厂
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
    }
}

IOC 和 DI(重点)

  • IOC:控制反转,将对象的创建权反转给了 Spring

    • DI(dependency injection):依赖注入,前提必须要有 IOC 的环境,Spring 在管理这个类的时候将类的依赖的属性注入(设置)进来
  • 面向对象的时候,对象和对象之间的关系:

    • 依赖
      有一个 A 类,一个 B 类,可能在 B 类的方法当中需要一个 A 类的对象,就说 B 依赖 A
Class A{
}

Class B{
    public void xxx(A a){
    }
}
  • 继承

  • 聚合

Spring 工厂类

Spring 工厂类的结构图

在这里插入图片描述

ApplicationContext 工厂继承了 BeanFactory,所以我们现在用的是 ApplicationContext。

BeanFactory:老版本的工厂类

  • BeanFactory:调用 getBean 的时候,才会生成类的实例。

ApplicationContext:新版本的工厂类

  • ApplicationContext:加载配置文件的时候,就会将 Spring 所管理的类都实例化。
  • ApplicationContext 有两个实现类:
    • ClassPathXmlApplicationContext:用来加载类路径下的配置文件
      类路径指的就是 src 下的
    • FileSystemXmlApplicationContext:用来加载文件系统下的配置文件,加载某个磁盘下的配置文件

Spring 的配置

XML 提示的配置

Bean 的相关配置

标签的 id 和 name 的配置
  • id:使用了约束中的唯一约束,里面不能出现特殊字符
  • name: 没有使用约束中的唯一约束(理论上可以出现重复的,但实际开发不能出现重复),里面可以出现特殊字符
Bean 的生命周期的配置(了解)
<!--Spring的Bean的生命周期的配置=================-->
    <bean id="customerDao" class="spring.demo2.CustomerImpl" init-method="setup" destroy-method="destory"/>
  • init-method:Bean 被初始化的时候执行的方法
  • destory-method:Bena 被销毁的时候执行的方法(Bean 是单例创建,工厂关闭)

Bean 的作用范围的配置(重点)

  • scope 属性:Bean 的作用范围
    • singleton:默认的,Spring 会采用单例模式(不管有多少程序调用,只会得new一次,每一次用的都是同一个对象)创建对象
    • prototype:多例模式(在 Structs2 和 Spring 整合一定会用到)
    • request:应用在 web 项目中,Spring 创建这个类以后,将这个类存入到 request 范围中
    • session:应用在 web 项目中,Spring 创建这个类以后,将这个类存入到 session 范围中
    • globalsession:应用在 web 项目中,必须在 prolet 环境下使用

Spring 属性注入

给 Bean 中的属性设置值:

构造方法方式
public class User{
    private String name;
    private String password;
    public User(String name, String password){
        this.name = name;
        this.password = password;
    }
}
构造方法的方式的属性注入
<!--Spring的属性注入的方式================-->
    <!--构造方法的方式-->
    <bean id="car" class="spring.deomo3.Car">
        <constructor-arg name="name" value="宝马"/>
        <constructor-arg name="price" value="800000"/>
    </bean>
set 方法方式
public class User{
    private String name;
    public void setName(String name){
        this.name = name;
    }
}
set方法的方式的属性注入
<!--set方法的方式-->
    <bean id="car2" class="spring.deomo3.Car2">
        <property name="name" value="奔驰"/>
        <property name="price" value="1000000"/>
    </bean>

    <!--set方法注入对象类型的属性-->
    <bean id="employee" class="spring.deomo3.Employee">
        <!--value:设置普通类型的值,ref:设置其他的类的id或name-->
        <property name="name" value="小明"/>
        <property name="car2" ref="car2"/>
    </bean>
接口注入的方式
public interface Injection{
    public void setName(String name);
}

public class User implements Injection{
    private String name;
    public void setName(String name){
        this.name = name;
    }
}

Spring 当中的属性注入支持前两种

构造方法方式的属性注入
public class Car {
    private String name;
    private Double price;
    
	public Car(String name, Double price) {
		super();
		this.name = name;
		this.price = price;
	}

	@Override
	public String toString() {
		return "Car [name=" + name + ", price=" + price + "]";
	}  
}


/**
 * @author Administrator
 * 属性注入的方式
 */
public class SpringDemo4 {
    @Test
    public void demo1() {
    	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    	Car car = (Car) applicationContext.getBean("car");
    	System.out.println(car);
    }
}


  <!-- Spring的属性注入的方式 -->
       <!-- 构造方法的方式(属性注入的一个前提是bean交给spring管理)-->
       <bean id="car" class="spring.demo4.Car">
           <constructor-arg name="name" value="宝马"/>
           <constructor-arg name="price" value="800000"/>
       </bean>
Set方法方式的属性注入
public class Car2 {
    private String name;
    private Double price;
    
	public void setName(String name) {
		this.name = name;
	}
	public void setPrice(Double price) {
		this.price = price;
	}
	
	
	@Override
	public String toString() {
		return "Car2 [name=" + name + ", price=" + price + "]";
	}
       
}

/**
     * @author Administrator
     * set方式的属性注入
     */
    @Test
    public void demo2() {
    	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    	Car2 car2 = (Car2) applicationContext.getBean("car2");
    	System.out.println(car2);
    }

<!-- set方法的方式 -->
       <bean id="car2" class="pring.demo4.Car2">
           <property name="name" value="奔驰"/>
           <property name="price" value="1000000"/>   
       </bean>

以上注入的属性的类型都是普通的类型,但是如果属性中有对象类型该怎么办?

public class Employee {
    private String name;
    private Car2 car2;
    
    public void setName(String name) {
    	this.name = name;
    }
    
    public void setCar2(Car2 car2) {
    	this.car2 = car2;
    }

	@Override
	public String toString() {
		return "Employee [name=" + name + ", car2=" + car2 + "]";
	}   
}

<!-- set方法注入对象类型的属性 -->
       <bean id="employee" class="spring.demo4.Employee">
       <!-- value:设置普通类型的值,ref:设置其他类型的id或name -->
           <property name="name" value="张三"/>
           <property name="car2" ref="car2"/>
       </bean>


P 名称空间的属性注入
  • 通过引入 p 名称空间完成属性的注入:
    写法:
    普通属性:p:属性名=“值”
    对象属性:p:属性名-ref=“值”
    首先要引入p名称空间
    在这里插入图片描述

  • 使用 p 名称空间(Spring2.5以后的版本)

 <!--改为p名称空间的方式==============-->
    <bean id="car2" class="spring.deomo3.Car2" p:name="奇瑞" p:price="30000"></bean>
    <bean id="employee" class="spring.deomo3.Employee" p:name="王东" p:car2-ref="car2"></bean>
SpEL 的属性注入(Spring3.0以后的版本)
  • SpEL:Spring Expression Language,Spring 的表达式的语言
    语法:
    #{SpEL}
<!--SpEL的属性注入-->    
    <bean id="car2" class="spring.deomo3.Car2">
        <property name="name" value="#{'三蹦子'}"></property>
        <property name="price" value="#{3000}"></property>
    </bean>

    <bean id="employee" class="spring.deomo3.Employee">
        <property name="name" value="#{'赵洪'}"></property>
        <property name="car2" value="#{car2}"></property>
    </bean>

在 #{SpEL} 中还可以更加灵活的使用,比如调用对象的属性,调用对象的方法,写相关表达式等等

<!--SpEL的属性注入-->
    <bean id="carInfo" class="spring.deomo3.CarInfo"></bean>

    <!--SpEL 中还可以调用其他类的属性或方法-->
    <bean id="car2" class="spring.deomo3.Car2">
        <property name="name" value="#{carInfo.name}"></property>
        <property name="price" value="#{carInfo.caculatePrice()}"></property>
    </bean>

    <bean id="employee" class="spring.deomo3.Employee">
        <property name="name" value="#{'赵洪'}"></property>
        <property name="car2" value="#{car2}"></property>
    </bean>
复杂数据类型的属性注入
  • 数组、集合的属性注入
<!--Spring集合属性的注入===========-->
    <!--注入数组类型-->
    <bean id="collectionBean" class="spring.demo4.CollectionBean">
        <!--数组类型-->
        <property name="arrs">
            <list>
                <value>小明</value>
                <value>小王</value>
                <value>小强</value>
            </list>
        </property>

        <!--集合类型-->
        <property name="list">
            <list>
                <value>李冰</value>
                <value>李水</value>
                <value>李小水</value>
            </list>
        </property>

        <!--注入set集合-->
        <property name="set">
            <set>
                <value>aaa</value>
                <value>bbb</value>
            </set>
        </property>

        <property name="map">
            <map>
                <entry key="aaa" value="111"></entry>
                <entry key="bbb" value="222"></entry>
                <entry key="ccc" value="333"></entry>
            </map>
        </property>
    </bean>

Spring 分模块开发的配置

分模块配置
在加载配置文件时候,加载多个
  1. 在加载配置文件的时候使用多变量参数
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");
在一个配置文件中引入多个配置文件
 <import resource="applicationContext2.xml"/>

CRM 综合案例

搭建开发环境
创建数据库和表
创建 web 项目,引入 jar 包
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值