1.Spring核心思想
(1)基本概念
IoC(Intversion of Control):控制反转,控制权从应用程序转移到框架,这是框架的共有特性。
IoC容器:实现了IoC思想的容器就是IoC容器,比如:SpringFramework,Guice
DI:依赖注入(Depedency Injection):用一个单独的对象(装配器)来配对对象之间的依赖关系。
(2)了解IoC容器特点
不需要主动new对象,而是描述对象应该如何被创建即可,IoC容器帮你创建,即被动实例化;
不需要主动装配装配对象之间的依赖关系,而是描述需要哪个服务(组件),IoC容器会帮你装配(即负责将它们关联在一起),被动接受装配;
主动边被动,好莱坞法则:别打电话给我们,我们打电话给你;
迪米特法则(最少知识原则):不知道依赖的具体实现,只知道需要的提供某类服务的对象(面向对象的原则),松散耦合,一个对象应当对其他对象有尽可能少的了解,不和陌生人(实现)说话;
IoC是一种让服务消费者不依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。
(3)理解Ioc容器问题关键
谁控制谁?为什么叫反转?
答:IoC容器控制,而以前是应用程序控制,所以叫做反转。
控制什么?
答:控制应用程序所需要的资源(对象、文件……)。
控制的哪些方面被反转了?
答:程序的控制权发生了反转,从应用程序转移到了IoC容器。
(4)理解实现IoC思想的容器
容器:提供组件运行环境,管理组件生命周期(不管组件如何创建的以及它们之间的关系)
IoC容器不仅仅具有容器的功能,而且还具有一些其他的特性,比如依赖装配。
由于控制反转概念太广泛,所以后来Martin Fowler提出依赖注入——DI容器概念。
在后来我们将IoC和控制反转都叫DI
(5)理解DI问题关键
*谁依赖谁?
应用程序依赖IoC容器
*为什么依赖?
应用程序依赖IoC容器装配类之间的关系
*依赖什么东西?
依赖IoC容器的装配功能
*谁注入谁?
IoC容器注入应用程序
*注入什么东西?
注入应用程序需要的资源(类之间的关系)
DI容器:主要我们的IoC容器具备了依赖功能我们就叫做DI容器。我们的Spring框架是一个DI容器。
(6)理解DI优点
*帮你看清组件之间的依赖关系,只需要观察依赖注入的机制(setter/构造器),就可以掌握整个依赖(类与类之间的关系)
*组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件中。
*依赖关系注入的目标并非为软件系统带来更多的功能,而是为了提升组件重用的概率,并未系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不用关心具体的资源来源。
注意:使用DI限制,组件(我们自己写的)和装配器(IoC容器)之间不会有依赖关系(有没有关系就看有没有导入它的包),因此组件无法从适配器那里获得更多服务,只能获得配置信息中所提供的那些。
2.Spring框架的设计哲学
Spring框架的原则:
在每个层次偶提供选择: Spring允许你尽可能推迟设计决策。你可以不更改代码的情况下通过配置切换持久化性提供者。
容纳不同的观点: 拥抱变化。
保持强烈的向后兼容性: Spring支持精心选择的JDK版本和第三方库,以促进依赖于Spring的应用程序和库的维护。
关心API设计: Spring团队将大量思想和时间投入到制作api。
二、Spring生态
关系数据库:
非关系数据库:
三、Spring应用案例(spring官网:https://spring.io/)
实现计算图形面积和周长:
(1)pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wschase.springcore</groupId>
<artifactId>springcore-maven-case</artifactId>
<version>1.0.0</version>
<!--Spring框架的物料清单-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--Spring框架依赖-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
</project>
(2)application-context.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--容器里面关于对象信息的描述-->
<bean id="circular" class="com.wschase.spring.common.impl.Circular">
<constructor-arg name="radius" value="10"/>
</bean>
<bean id="triangle" class="com.wschase.spring.common.impl.Triangle">
<constructor-arg name="a" value="10"/>
<constructor-arg name="b" value="24"/>
<constructor-arg name="c" value="20"/>
</bean>
<bean id="rectangle" class="com.wschase.spring.common.impl.Rectangle">
<constructor-arg name="height" value="10"/>
<constructor-arg name="width" value="20"/>
</bean>
<!--容器会根据这些信息来创建我们的对象-->
<bean id="xmlShapeCompute" class="com.wschase.spring.xml.XmlShapeCompute">
<property name="circular" ref="circular"/>
<property name="rectangle" ref="rectangle"/>
<property name="triangle" ref="triangle"/>
</bean>
</beans>
(3)计算图形面积、周长的接口
package com.wschase.spring.common;
/**
* Author:WSChase
* Created:2019/4/17
*/
public interface Shape {
/**
* 计算图形面积
* @return
*/
double computeArea();
/**
* 计算图形周长
* @return
*/
double computeSide();
}
(4)圆、长方形、三角形各自的类
package com.wschase.spring.common.impl;
import com.wschase.spring.common.Shape;
/**
* Author:WSChase
* Created:2019/4/17
*/
public class Circular implements Shape {
private final double radius;
public Circular(double radius) {
this.radius = radius;
}
public double computeArea() {
return Math.PI*Math.pow(this.getRadius(),2);
}
public double computeSide() {
return 2*Math.PI*this.getRadius();
}
//fianl类型只有set方法
public double getRadius() {
return radius;
}
@Override
public String toString() {
return "Circular{" +
"radius=" + radius +
",area="+this.computeArea()+
",side="+this.computeSide()+
'}';
}
}
package com.wschase.spring.common.impl;
import com.wschase.spring.common.Shape;
/**
* Author:WSChase
* Created:2019/4/17
*/
public class Rectangle implements Shape {
//宽
private final double width;
private final double height;
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
//高
public double computeArea() {
return this.getWidth()*this.getHeight();
}
public double computeSide() {
return 2*(this.getHeight()+this.getWidth());
}
@Override
public String toString() {
return "Rectangle{" +
"width=" + width +
", height=" + height +
",area="+this.computeArea()+
",side="+this.computeSide()+
'}';
}
}
package com.wschase.spring.common.impl;
import com.wschase.spring.common.Shape;
/**三角形
* Author:WSChase
* Created:2019/4/17
*/
public class Triangle implements Shape {
private final double a;
private final double b;
private final double c;
public Triangle(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
public double getA() {
return a;
}
public double getB() {
return b;
}
public double getC() {
return c;
}
public double computeArea() {
double q=(this.computeSide())/2;
double s=Math.sqrt(
(q-a)*(q-b)*(q-c)*q
);
return 0;
}
public double computeSide() {
return this.getA()+this.getB()+this.getC();
}
@Override
public String toString() {
return "Triangle{" +
"a=" + a +
", b=" + b +
", c=" + c +
",area="+this.computeArea()+
",side="+this.computeSide()+
'}';
}
}
(5)
package com.wschase.spring.xml;
import com.wschase.spring.common.Shape;
/**
* Author:WSChase
* Created:2019/4/17
*/
public class XmlShapeCompute {
public Shape circular;
public Shape triangle;
public Shape rectangle;
public Shape getCircular() {
return circular;
}
public void setCircular(Shape circular) {
this.circular = circular;
}
public Shape getTriangle() {
return triangle;
}
public void setTriangle(Shape triangle) {
this.triangle = triangle;
}
public Shape getRectangle() {
return rectangle;
}
public void setRectangle(Shape rectangle) {
this.rectangle = rectangle;
}
public Shape computeShape(String shapeName){
if(shapeName==null||shapeName.length()==0){
throw new IllegalArgumentException("Not found shape");
}
if(shapeName.equals("circular")){
return circular;
}
if(shapeName.equals("triangle")){
return triangle;
}
if(shapeName.equals("rectangle")){
return rectangle;
}
throw new IllegalArgumentException("Not found shape"+shapeName);
}
}
(6)主类:
package com.wschase.spring.xml;
import com.wschase.spring.common.Shape;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**这是一个主类
* Author:WSChase
* Created:2019/4/17
*/
public class XmlApplication {
public static void main(String[] args) {
//我们通过new的方式创建了一个容器
ApplicationContext context=
new ClassPathXmlApplicationContext("application-context.xml");
//在容器里面取找这个name(id)对应的对象,找到之后会将对象返回给我们:
// 这个时候我们获取对象就没有通过new来创建对象
XmlShapeCompute xmlShapeCompute= (XmlShapeCompute) context.getBean("xmlShapeCompute");
Shape shape=xmlShapeCompute.computeShape(args[0]);
System.out.println(shape);
}
}
从上面的例子我们可以看出来我们并没有通过new来实例化对象,而是通过容器寻找到对象相关的信息,它返回给我们需要的对象。