spring是一站式开发框架,即Spring在JavaEE的三层架构:表现层(Web层)、业务逻辑层(Service 层)、数据访问层(DAO即Data Access Object ) 中,每一层均提供了不同的解决技术。
spring框架的特点:
轻量级: Spring在大小和透明性方面绝对属于轻量级的,基础版本的Spring框架大约只有2MB
控制反转 :Spring使用控制反转技术实现了松耦合。依赖被注入到对象,而不是创建或寻找依赖对象
面向切面编程(AOP):Spring支持面向切面编程,同时把应用的业务逻辑与系统的服务分离开来
容器:Spring包含并管理应用程序对象的配置及生命周期
MVC框架:Spring的web框架是一个设计优良的Web MVC框架,很好的取代了一些web框架
事务管理:Spring对下至本地业务上至全局业务(JAT)提供了统一的事务管理接口
异常处理:Spring提供一个方便的API将特定技术的异常(由JDBC, Hibernate, 或JDO抛出)转化为一致的、 Unchecked异常
Core Container:管理对象的生命周期
非CRUD操作抽象为一个类:AOP
IoC:控制反转
将控制权从应用程序转移到框架(在面向对象中,解除两个类之间的关系,可以通过一个接口来进行控制反转,因此在这里也可以将IoC容器理解为一个接口进行了关系反转)
IoC容器可以创建对象,只需要提供某类服务对象,松散耦合,减少类与类之间依赖的设计原则
DI:依赖注入
依赖注入用一个单独的对象(装配器)来装配对象之间的依赖关系
对于IoC创建的对象,主动将对象像打针一样的方式注入到类中,DI有三种方式:getter/setter方法/j接口/构造方法(因此IOC需要创建这些关系)
因此以后在程序中,不需要继承某个类,因为这样会将两个类永远绑定起来了,因此采用接口优先的原则
IoC 和DI是相辅相成的,他们共同作用,达到控制反转,依赖注入的目的
SpringIoC的构建
SpringIoC的构建方式一共有三种:
- 基于XML配置(可以开启注解配置,通过注解配置和Bean和装配工作)
- 基于Goovy脚本配置的方式
- 基于java Config的配置注解的方式(主要通过Configuration和Bean注解)
在java中我们创建一个实例,一般是通过关键字new的方式创建,初始化实例的方式有:利用构造方法或是setter方法,对应到Spring中在XML配置Bean的实例化如下:
Bean的实例化
实例化即为创建对象,在javaSE中就是使用new关键字
一般创建对象有发生以下四个步骤:
1.开辟空间
2.初始化成员变量
3.调用默认构造器
4.堆中创建的对象赋值给栈中的引用
创建对象:
<bean id="circular" class="com.sweeeeeet.github.ioc.apply.Circular">
</bean>
id属性的值相当对象名
Bean的依赖装配
通过构造方法初始化实例对象:
<bean id="rectangle" class="com.sweeeeeet.github.ioc.apply.Rectangle">
<constructor-arg name="height" value="15"/>
<constructor-arg name="width" value="20"/>
</bean>
name属性表示这个类的实例属性名称,value表示为属性赋的值,
还可以根据在构造方法中参数的位置index进行赋值<constructor-arg index="0" value="7500000"/>
还可以根据构造方法中参数 的类型type进行赋值:<constructor-arg type="int" value="7500000"/>
使用constructor-arg这种方式初始化,就需要在本来的类中创建相应的构造方法
通过setter方法初始化实例对象:
<!--创建对象-->
<bean id="person" class="com.sweeeeeet.github.ioc.practice.UserInfo">
<!--通过set方法为对象初始化-->
<property name="car" ref="car"/>
<property name="name" value="张三"/>
<property name="sex" value="女"/>
</bean>
ref表示在Bean中已经创建好的对象(id中的值),返回到类中的也同样是一个实例化对象
使用property初始化就需要在相应的类中编写setter方法,并且利用setter方法注入时,必须存在无参构造(在存在有参构造的情况下)
IoC与DI的实际应用
利用接口摆脱类与类之间的绑定关系
package com.sweeeeeet.github.ioc.apply;
/**
* Author:sweet
* Created:2019/5/19
*/
public interface IShape {
/*
* 计算图形的面积
* */
double computeArea();
/*
* 计算图形的边长
* */
double computeSide();
}
实现类
package com.sweeeeeet.github.ioc.apply;
/**
* Author:sweet
* Created:2019/5/19
*/
public class Circular implements IShape{
private final double radius;
//包含构造方法,因此在xml文件中采用构造注入的方式
public Circular(double radius) {
this.radius = radius;
}
@Override
public double computeArea() {
return Math.PI*Math.pow(radius,2);
}
@Override
public double computeSide() {
return radius;
}
public double getRadius(){
return radius;
}
@Override
public String toString() {
return "Circular{" +
"radius=" + radius +
'}';
}
}
package com.sweeeeeet.github.ioc.apply;
/**
* Author:sweet
* Created:2019/5/19
*/
//利用接口控制反转
public class Rectangle implements IShape{
//类中的属性依赖注入
private final double width;
private final double height;
//包含构造方法,因此在xml文件中采用构造注入的方式
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double computeArea() {
return width*height;
}
@Override
public double computeSide() {
return (width+height)*2;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
@Override
public String toString() {
return "Rectangle{" +
"width=" + width +
", height=" + height +
'}';
}
}
业务调用类
package com.sweeeeeet.github.ioc.apply;
/**
* Author:sweet
* Created:2019/5/19
*/
public class XMLShapeCompute {
private IShape circular;
private IShape rectangle;
//编写set方法,就可以利用setter方法注入的方式
public void setCircular(IShape circular) {
this.circular = circular;
}
public void setRectangle(IShape rectangle) {
this.rectangle = rectangle;
}
public IShape compute(String shap){
if(shap.equals("circular")){
return circular;
}
if(shap.equals("rectangle")){
return rectangle;
}
return null;
}
}
配置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-3.0.xsd">
<!--配置类-->
<!--Circular类中属性通过构造方法的方式注入-->
<bean id="circular" class="com.sweeeeeet.github.ioc.apply.Circular">
<constructor-arg name="radius" value="20"/>
</bean>
<!--Rectangle类中属性通过setter方法的方式注入-->
<bean id="rectangle" class="com.sweeeeeet.github.ioc.apply.Rectangle">
<constructor-arg name="height" value="15"/>
<constructor-arg name="width" value="20"/>
</bean>
<!---->
<bean name="shapeCompute" class="com.sweeeeeet.github.ioc.apply.XMLShapeCompute">
<!--因为在XMLShapeCompute中,需要的是一个返回值,他是IShape接口的实现类对象,因此set注入采用ref-->
<property name="circular" ref="circular"/>
<property name="rectangle" ref="rectangle"/>
</bean>
</beans>
单元测试:
package main.com.sweeeeeet.github.ioc.test;
import com.sweeeeeet.github.ioc.practice.Car;
import com.sweeeeeet.github.ioc.practice.UserInfo;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Author:sweet
* Created:2019/5/19
*/
public class CarIoCTest {
private ApplicationContext context=null;
private Car car=null;
private UserInfo person=null;
@Before
public void testInit(){
context=new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void testFunc(){
car=(Car) context.getBean("car");
person=(UserInfo) context.getBean("person");
person.haveCar(true);
}
}