Spring的概述
- spring是什么
spring是分层的Java EE/SE应用 全栈型轻量级开发框架,以IOC和AOP为内核提供了展现层SpringMVC和持久层Spring JDBC以及业务层事务管理的企业级应用技术。 - spring的两大核心
IOC和AOP
IOC(Inversion of control):控制反转又称依赖注入
AOP(Aspect Oriented Programming):面向切面编程 - spring的发展历程和优势
Rod Johnson (spring之父)
2017年9月发布了spring的最新版本spring 5.0通用版
优势:方便解耦简化开发 - spring体系结构
程序的耦合和解耦
- 曾经案例中的问题
耦合:可以理解为程序间的依赖关系,包括类之间的依赖和方法之间的依赖
解耦:降低程序间的依赖关系
解耦思路:
第一步:使用反射创建对象,而避免使用new关键字
第二步:通过配置文件来获取创建的对象 - 工厂模式解耦
一个创建bean对象的工厂,来创建service和dao对象
第一:需要一个配置文件配置service和dao
配置内容:唯一标识和全限定名(key=value)
第二:通过读取配置文件中的配置内容,反射创建对象
配置文件可以是xml或者properties
PS:
bean:在计算机英语中有可重用组件的含义
Javabean:用Java语言编写可重用组件,它所表示的范畴远大于实体类。
IOC概念和Spring中的IOC
- spring中基于xml的IOC环境搭建
<?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">
<!--把对象的创建交给spring来管理-->
<bean id="accountDao" class="org.example.dao.impl.AccountDaoImpl" ></bean>
<!--spring 对bean的细节管理
1,创建bean的三种方式
2,bean对象的作用范围
3,bean对象的生命周期
-->
<!--创建Bean的三种方式-->
<!--第一种方式:使用默认构造函数创建
在spring配置文件中使用bean标签,配以ID和class属性后,且没有其他属性标签时
采用的就是默认构造函数创建bean对象,如果此时类中没有默认构造函数,则对象无法创建-->
<bean id="accountService" class="org.example.service.impl.AccountServiceImpl" ></bean>
<!--第二种方式:使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器) -->
<bean id="instanceFactory" class="org.example.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
<!--第三种方式:使用工厂中的静态方式创建对象(使用某个类中的静态方法创建对象,并存入spring容器)-->
<bean id="accountService" class="org.example.factory.StaticFactory" factory-method="getAccountService"></bean>
<!--bean的范围调整
bean的scope属性:作用是指定bean的作用范围调整
取值:
singleton:单例(默认值)
prototype:多例的
request:作用于web请求范围
session:作用于web回话范围
global-session:作用于集群环境的回话范围(全局回话范围),当不是集群环境时,她就是session-->
<bean id="accountService" class="org.example.service.impl.AccountServiceImpl" scope="prototype"></bean>
<!--bean对象的生命周期
单例对象:
出生:当容器创建时
活着:当容器还在
死亡:当容器销毁
多例对象
出生:使用对象时spring为我们创建
活着:使用过程中一直活着
消亡:当对象长时间不用,且没有别的对象引用时,Java的垃圾回收器回收
-->
<bean id="accountService" class="org.example.service.impl.AccountServiceImpl" scope="singleton"
init-method="ini" destroy-method="destroy"></bean>
</beans>
依赖注入
构造方法注入:
<!--spring 依赖注入
依赖注入:Dependency Injection
IOC的作用:降低程序间的耦合
依赖关系管理:以后都交给spring来维护
当前类所需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明依赖
关系的维护 :就称之为依赖注入
能注入的数据类型有三类:
基本类型和String
其他bean类型(在配置文件中或者配置注解过的bean)
复杂类型/集合类型
注入的方式有三种
使用构造函数提供
使用set方法提供
使用注解提供-->
<!--构造函数注入:
type:用于指定要注入的数据类型,该数据类型也是构造方法中某个或者某些的类型
index:用于指定要注入的数据给构造函数找那个指定索引位置的参数赋值,索引的位置是从0开始的
name:用于指定给构造函数中的指定参数赋值(一般使用这种方式)
-----------------------------以上是给构造函数参数赋值的三种方法----------------------
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型,它指的就是在IOC核心容器中配置过出现过的bean对象
优势:
在获取bean对象时,注入数据是必须的操作,否则对象将无法创建成功
劣势:
改变了bean对象的实例化方法,使我们在创建对象时,如果用不到这些数据也必须提供-->
<bean id="accountService" class="org.example.service.impl.AccountServiceImpl">
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="name" value="test"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<!--配置一个日期对象-->
<bean id="now" class="java.util.Date"></bean>
set方法注入
项目结构
bean.xml
<!--set方法注入(更常用):
涉及的标签:property
出现的位置:bean内部标签
标签的属性:
value:用于提供String类型和基本类型的数据
name:用于指定调用set方法名称
ref:用于指定其他的bean类型数据。他指的是在spring的IOC容器出现过的bean对象
-->
<bean id="accountService" class="org.example.service.impl.AccountServiceImpl">
<property name="userName" value="tom"></property>
<property name="age" value="12"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
Client.java
package org.example.ui;
import org.example.service.IAccountService;
import org.example.service.impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Client {
/**
* 获取spring的IOC容器,并根据ID创建对象
* ApplicationContext的三个常用实现类
* ClassPathXmlApplicationContext:可以加载类路径下的配置文件,要求配置文件必须在类路径下,不在的话加载不了
* FileSystemXmlApplicationContext:可以加载磁盘任意路径下的配置文件,必须有权限
* 比较前两个类第一个比较常用
* AnnotationConfigApplicationContext:用于读取注解创建容器
*
* 核心容器两个接口引发的问题:
*ApplicationContext:(单例对象适用)
* 它在构建核心容器时,创建对象所采取的策略是立即加载方式,也就是说,只要一读完配置文件马上创建配置文件中的对象
* BeanFactory:(多例对象适用)
* 它在构建核心容器时,创建对象所采用的策略是延时加载方式,也就是说,什么时候ID获取对象了,什么时候才真正创建对象
* @param args
*/
public static void main(String[] args){
//获取核心对象
// ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//根据ID获取对象
IAccountService as1 = (IAccountService) ac.getBean("accountService");
as1.saveAccount();
//手动关闭
ac.close();
}
}
接口IAccountService.java
package org.example.service;
public interface IAccountService {
void saveAccount();
}
实现类AccountServiceImpl .java
package org.example.service.impl;
import org.example.service.IAccountService;
import java.util.Date;
public class AccountServiceImpl implements IAccountService {
private String userName;
private Integer age;
private Date birthday;
public AccountServiceImpl() {
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public AccountServiceImpl(String name, Integer age, Date birthday){
this.age = age;
this.birthday = birthday;
this.userName = name;
}
//业务层调用持久层
public void saveAccount() {
System.out.println("service method !"+userName+","+age+","+birthday);
}
}
复杂型/集合型注入
bean.xml
<!--复杂类型的注入/集合类型的注入
list结构类型注入的标签:list array set
map结构类型的标签 map props
结构相同的标签可以互换-->
<bean id="accountService2" class="org.example.service.impl.AccountServiceImpl2">
<property name="myStr">
<array>
<value>aaa</value>
<value>bbb</value>
<value>bbb</value>
</array>
</property>
<property name="myList">
<list>
<value>vvv</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="myMap">
<props>
<prop key="testD ">fff</prop>
<prop key="testE">hhh</prop>
</props>
</property>
<property name="myProps">
<map>
<entry key="testA" value="111"></entry>
<entry key="testB" value="121"></entry>
<entry key="testC" >
<value>ccc</value>
</entry>
</map>
</property>
<property name="mySet">
<set>
<value>how</value>
<value>old</value>
<value>are</value>
<value>you</value>
</set>
</property>
</bean>
package org.example.ui;
import org.example.service.IAccountService;
import org.example.service.impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Client {
public static void main(String[] args){
//获取核心对象
// ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//根据ID获取对象
IAccountService as = (IAccountService) ac.getBean("accountService2");
as.saveAccount();
}
}
package org.example.service.impl;
import org.example.service.IAccountService;
import java.lang.reflect.Array;
import java.util.*;
public class AccountServiceImpl2 implements IAccountService {
public void setMyStr(String[] myStr) {
this.myStr = myStr;
}
public void setMyList(List<String> myList) {
this.myList = myList;
}
public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
}
public void setMyProps(Properties myProps) {
this.myProps = myProps;
}
private String[] myStr;
private List<String> myList;
private Set<String> mySet;
private Map<String,String> myMap;
private Properties myProps;
//业务层调用持久层
public void saveAccount() {
System.out.println(Arrays.toString(myStr));
System.out.println(myList);
System.out.println(mySet);
System.out.println(myProps);
System.out.println(myMap);
}
}