文章目录
Spring 概述
优点
-
方便解耦,由Spring来控制对象间的依赖关系
-
AOP面向切面编程,可以实现一些OOP无法实现的功能
-
可以通过声明式灵活进行事务的管理
-
方便集成各类框架,如SSM整合
-
降低API使用难度
-
有能力的话阅读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();
}
}
耦合可以认为是程序间的依赖关系,包括
- 类之间的耦合关系
- 方法之间的耦合关系
解耦
不可能完全消除依赖关系,但是可以降低,在实际的开发中做到
编译时不依赖,运行时才依赖
解耦的常用思路:
- 用反射来创建对象,而避免使用new关键字
- 通过读取配置文件来获取要创建的对象全限定类名
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的四个核心容器
- Beans
- Core
- Spel
- context
配置文件的方式
-
Properties中的配置
accountService=com.itheima.service.impl.AccountServiceImpl accountDao=com.itheima.dao.impl.AccountDaoImpl
-
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有很多实现类,我们主要学习三个
- ClassPathXmlApplicationContext:类路径加载 (实际开发中常用)
- FileSystemXmlApplicationContext:文件系统路径加载
- AnnotationConfigApplicationContext:用于基于注解的配置
- WebApplicationContext:专门为web应用准备的,从相对于Web根目录的路径中装载配置文件完成初始化
BeanFactory 和 ApplicationContext 的区别
BeanFactory | ApplicationContext |
---|---|
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化; | ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化 |
应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势; | 所有的Bean在启动的时候都加载,系统运行的速度快 |
在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题 | |
建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成) |
创建Bean对象
创建有三种方式:
-
使用默认构造函数
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
-
使用静态方法创建对象
public class StaticFactory { public static IAccountService getAccountService(){ return new AccountServiceImpl(); } }
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
-
使用普通工厂中的方法来创建
如果我们的对象是这样定义的
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>
-
singleton 单例 (默认)
-
prototype 多例
-
request
-
session
-
global-session 作用于集群会话范围
Bean的生命周期
单例和多例的生命周期不同
-
单例对象 (和容器共生死)
public static void main(String[] args) { //1.获取核心容器 ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); IAccountService as = (IAccountService) ac.getBean("accountService"); ac.close(); }
-
多例对象
init:
live:在使用过程中一直存活
destroy:当对象长时间不用且没有别的对象引用时,使用垃圾回收机制
依赖注入
Dependency Injection ,依赖关系的维护就称作依赖注入
- 依赖注入的三种类型
- 基本类型和String
- 其他bean类型
- 复杂/集合类型
- 注入的三种方式
如果是经常变化的数据,不建议用注入。
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>
- 用于给List结构集合注入的标签
- list
- array
- set
- 用于给Map结构集合注入的标签
- map
- props
主要是看集合的结构!!
回顾本文
- IOC的作用是什么
- 依赖注入的作用是什么
- Bean 的创建方式有哪几种?
- 单例和多例?
- 如何去搭建Spring+xml 环境
- 各种注入方式
- 回顾注解相关的知识