Java笔记 - Spring 框架 -1

Spring 概述

优点

  1. 方便解耦,由Spring来控制对象间的依赖关系

  2. AOP面向切面编程,可以实现一些OOP无法实现的功能

  3. 可以通过声明式灵活进行事务的管理

  4. 方便集成各类框架,如SSM整合

  5. 降低API使用难度

  6. 有能力的话阅读Spring源码,学习JAVA的设计模式

程序耦合/解耦

在maven中,我们使用如下配置,设置好mysql的驱动

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
</dependencies>

在Demo中使用这个依赖

public class JdbcDemo1 {
    public static void main(String[] args) throws SQLException {
        //标准的写法,使用依赖的jar包(使用maven配置)
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/eesy?useUnicode=true&characterEncoding=utf8", "root", "danangua");
        PreparedStatement pstm = conn.prepareStatement("select * from account");
        ResultSet re = pstm.executeQuery();
        while (re.next()) {
            System.out.println(re.getString("name"));
        }
        re.close();
        pstm.close();
        conn.close();
    }
}

耦合可以认为是程序间的依赖关系,包括

  1. 类之间的耦合关系
  2. 方法之间的耦合关系

解耦

不可能完全消除依赖关系,但是可以降低,在实际的开发中做到

编译时不依赖,运行时才依赖

解耦的常用思路:

  1. 用反射来创建对象,而避免使用new关键字
  2. 通过读取配置文件来获取要创建的对象全限定类名

Bean 对象工厂

JavaBean :用java语言编写的可重用语言

使用Bean来创建service和dao对象,配置的内容,唯一标识=全限定类名(key=value)

配置文件可以是xml或者Properties,在这里我们先采用Properties来进行配置

package com.itheima.factory;

import java.io.InputStream;
import java.util.Properties;

public class BeanFactory {
    //定义
    private static Properties props;

    //使用静态代码块给pros赋值.
    static {
        try {
            //实例化对象并获取
            props = new Properties();
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化失败.");
        }
    }

    public static Object getBean(String beanName) {
        Object bean = null;
        try {
            String beanPath = props.getProperty(beanName);
            bean = Class.forName(beanPath).newInstance();
						//这是多例的创建模式,需要改进。
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }

}

使用改进的单例版,思路:将 对象名:实例对象 绑定起来存入一个Map中,之后可以调用

public class BeanFactory {
    //定义
    private static Properties props;
    //定义一个容器
    private static Map<String, Object> beans;

    //使用静态代码块给pros赋值.
    static {
        try {
            //实例化对象并获取
            props = new Properties();
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            beans = new HashMap<String, Object>();
            Enumeration keys = props.keys();
            //遍历枚举
            while (keys.hasMoreElements()){
                String key = keys.nextElement().toString();
                String beanPath = props.getProperty(key);
                Object value = Class.forName(beanPath).newInstance();
                beans.put(key,value); //存入
            }

        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化失败.");
        }
    }
    
    
    //重写一遍getBean方法(单例)
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

单例和多例

单例模式:对象只被创建一次

com.itheima.service.impl.AccountServiceImpl@2503dbd3
com.itheima.service.impl.AccountServiceImpl@2503dbd3
com.itheima.service.impl.AccountServiceImpl@2503dbd3
com.itheima.service.impl.AccountServiceImpl@2503dbd3
com.itheima.service.impl.AccountServiceImpl@2503dbd3

多例模式:对象被创建多次,执行效率没有单例高

单例模式输出对象,其实每个对象都是不同实例 (多例)

com.itheima.service.impl.AccountServiceImpl@2503dbd3
com.itheima.service.impl.AccountServiceImpl@4b67cf4d
com.itheima.service.impl.AccountServiceImpl@7ea987ac
com.itheima.service.impl.AccountServiceImpl@12a3a380
com.itheima.service.impl.AccountServiceImpl@29453f44

由于静态代码块只在类创建的时候执行一次,且优先执行。

IOC

控制反转(Inversion of Control,英文缩写为IoC)是框架的重要特征,做到控制反转需要一个容器来实现,就是我们所说的IoC容器,最常见的IoC容器是Spring。

//传统创建方式
IAccountService as = new AccountServiceImpl();
//IOC方式创建,将控制权交给了工厂
IAccountService as = (IAccountService) BeanFactory.getBean("accountService");

在这里插入图片描述

基于XML的IOC环境

本节讲述环境的搭建。

Spring的四个核心容器

  1. Beans
  2. Core
  3. Spel
  4. context

配置文件的方式

  1. Properties中的配置

    accountService=com.itheima.service.impl.AccountServiceImpl
    accountDao=com.itheima.dao.impl.AccountDaoImpl
    
  2. 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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 定义这个xml是专门用来配置beans的   -->
        <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
        <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
    </beans>
    

使用Spring来创建对象

public static void main(String[] args) {
    //1.获取核心容器
    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    //2.根据id获取对象(两种方法)
    IAccountService as = (IAccountService) ac.getBean("accountService");
    IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);
    System.out.println(as);
    System.out.println(adao);
}

ApplicationContext 的实现类

在这里插入图片描述

ApplicationContext有很多实现类,我们主要学习三个

  1. ClassPathXmlApplicationContext:类路径加载 (实际开发中常用)
  2. FileSystemXmlApplicationContext:文件系统路径加载
  3. AnnotationConfigApplicationContext:用于基于注解的配置
  4. WebApplicationContext:专门为web应用准备的,从相对于Web根目录的路径中装载配置文件完成初始化

BeanFactory 和 ApplicationContext 的区别

BeanFactoryApplicationContext
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化
应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;所有的Bean在启动的时候都加载,系统运行的速度快
在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题
建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)

创建Bean对象

创建有三种方式:

  1. 使用默认构造函数

    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
    
  2. 使用静态方法创建对象

    public class StaticFactory {
        public static IAccountService getAccountService(){
            return new AccountServiceImpl();
        }
    }
    
    <bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
    
  3. 使用普通工厂中的方法来创建

    如果我们的对象是这样定义的

    public class InstanceFactory {
        public IAccountService getAccountService(){
            return new AccountServiceImpl();
        }
    }
    

    那么在bean.xml中要这样去构造:

    <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory" ></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
    

Bean 的作用范围

bean标签的scope属性可以调整bean的作用范围

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="prototype"></bean>
  1. singleton 单例 (默认)

  2. prototype 多例

  3. request

  4. session

  5. global-session 作用于集群会话范围

Bean的生命周期

单例和多例的生命周期不同

  1. 单例对象 (和容器共生死)

    public static void main(String[] args) {
        //1.获取核心容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountService as = (IAccountService) ac.getBean("accountService");
        ac.close();
    }
    
  2. 多例对象

    init:

    live:在使用过程中一直存活

    destroy:当对象长时间不用且没有别的对象引用时,使用垃圾回收机制

依赖注入

Dependency Injection ,依赖关系的维护就称作依赖注入

  1. 依赖注入的三种类型
    1. 基本类型和String
    2. 其他bean类型
    3. 复杂/集合类型
  2. 注入的三种方式

如果是经常变化的数据,不建议用注入

public class AccountServiceImpl implements IAccountService {

    private Integer age;
    private String name;
    private Date birthday;

    public AccountServiceImpl(Integer age, String name, Date birthday) {
        this.age = age;
        this.name = name;
        this.birthday = birthday;
    }

    public void saveAccount() {
        System.out.println("service 中的save方法" + name + age + birthday);
    }

对应地,要在xml中如下构造

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    <constructor-arg name="name" value="tung"></constructor-arg>
    <constructor-arg name="age" value="18"></constructor-arg>
    <constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>

<bean id="now" class="java.util.Date"></bean>

Set注入 (常用)

如果对象中没有构造方法:

public class AccountServiceImpl implements IAccountService {

    private Integer age;
    private String name;
    private Date birthday;

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public void saveAccount() {
        System.out.println("service 中的save方法" + name + age + birthday);
    }

}

在xml中需要如下构造

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    <property name="name" value="tung"></property>
    <property name="age" value="19"></property>
    <property name="birthday" ref="now"></property>
</bean>

<bean id="now" class="java.util.Date"></bean>

set方法的优势:创建对象没有明确的限制 这是更常用的方法

劣势:如果有某个成员必须有值,那么set方法不能保证一定注入。

集合注入

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    <property name="myStrs">
        <array>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </array>
    </property>
</bean>

同理,list可以这样构造

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    <property name="myStrs">
        <list>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </list>
    </property>
</bean>
  1. 用于给List结构集合注入的标签
    1. list
    2. array
    3. set
  2. 用于给Map结构集合注入的标签
    1. map
    2. props

主要是看集合的结构!!

回顾本文

  1. IOC的作用是什么
  2. 依赖注入的作用是什么
  3. Bean 的创建方式有哪几种?
  4. 单例和多例?
  5. 如何去搭建Spring+xml 环境
  6. 各种注入方式
  7. 回顾注解相关的知识
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值