最近经历了许许多多的事情, 学习荒废了很久. 自己的目标成了摆设. 现在要奋起直追了. 最近发现了张果的博客. 应该是一个教师. 看了他写的 spring 系列的博客, 写的不错. 于是本文的内容参考自他的博客, 当然都是手打书写. 由于我感觉他写的博客篇幅过长. 我根据我的习惯进行拆分学习. 而且他的文章一系列很清楚. 也值得我去学习. 自己写博客就零零散散. 不是很系统.
spring 概述
spring 可以做很多事情, 它为企业级开发提供了丰富的功能. 但是这些功能的底层都依赖于它的两个核心特性, 控制反转 (IoC) 和面向切面(AOP),
本篇文章主要介绍 IoC.
现在 springboot 和 spring cloud 十分火爆, 还是有必要看看两者之间的关系的
Spring Boot 是 Spring 的一套快速配置脚手架, 可以基于 Spring Boot 快速开发单个微服务, Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具; Spring Boot 专注于快速, 方便集成的单个微服务个体, Spring Cloud 关注全局的服务治理框架; Spring Boot 使用了约束优于配置的理念, 很多集成方案已经帮你选择好了, 能不配置就不配置, Spring Cloud 很大的一部分是基于 Spring Boot 来实现, Spring Boot 可以离开 Spring Cloud 独立使用开发项目, 但是 Spring Cloud 离不开 Spring Boot, 属于依赖的关系.
IoC 基础
控制反转 IoC 是一种设计思想, DI(依赖注入)是实现 IoC 的一种方法.(下面的这张图画的太好了)
没有 IoC 的程序中我们使用面向对象编程对象的创建于对象间的依赖关系完全硬编码在程序中, 对象的创建由程序自己控制.
控制反转后将对象的创建转移给第三方.
IoC 是 spring 框架的核心内容, 使用多种方式完美的实现了 IoC, 可以使用 xml 配置, 也可以使用注解, 新版本的 spring 可以零配置实现 IoC.
使用 xml 配置方式实现 IoC
创建 maven 项目
pom 文件如下
- <?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.kevin</groupId>
- <artifactId>spring</artifactId>
- <version>1.0-SNAPSHOT</version>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <spring.version>4.3.0.RELEASE</spring.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- <version>4.10</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.8.9</version>
- </dependency>
- <dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib</artifactId>
- <version>3.2.4</version>
- </dependency>
- </dependencies>
- </project>
使用无参构造方法创建对象
新建一个 Music 类
- /**
- * 音乐
- *
- * @author: kevin
- * @Date: 2018/12/8
- */
- public class Music {
- public Music() {
- System.out.println("播放周杰伦的《七里香》");
- }
- }
resources 文件夹下新建 music.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">
- <bean id="jay" class="com.kevin.spring.demo1.entity.Music"></bean>
- </beans>
测试类
- package com.kevin.spring.demo1.test;
- import com.kevin.spring.demo1.entity.Music;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @author: kevin
- * @Date: 2018/12/8
- */
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("music.xml");
- Music jay = ctx.getBean("jay", Music.class);
- }
- }
运行结果
信息: Loading xml bean definitions from class path resource [music.xml]
播放周杰伦的《七里香》
使用有参构造方法创建对象
- Person
- package com.kevin.spring.demo2.entity;
- /**
- * 人类
- */
- public abstract class Person {
- public String name;
- }
- Student
- package com.kevin.spring.demo2.entity;
- /**
- * 学生
- */
- public class Student extends Person{
- /**
- * 身高
- */
- public int height;
- /**
- * 有参构造函数
- * @param name
- * @param height
- */
- public Student(String name,int height) {
- this.name = name;
- this.height = height;
- }
- @Override
- public String toString() {
- return "Student{" +
- "height=" + height +
- ", name='" + name + '\'' +
- '}';
- }
- }
student.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">
- <bean id="kevin" class="com.kevin.spring.demo2.entity.Student">
- <constructor-arg name="name" value="kevin"></constructor-arg>
- <constructor-arg name="height" value="170"></constructor-arg>
- </bean>
- <!-- 使用索引指定参数 -->
- <bean id="maomao" class="com.kevin.spring.demo2.entity.Student">
- <constructor-arg index="0" value="maomao"></constructor-arg>
- <constructor-arg index="1" value="100"></constructor-arg>
- </bean>
- </beans>
测试类
- package com.kevin.spring.demo2.test;
- import com.kevin.spring.demo2.entity.Person;
- import com.kevin.spring.demo2.entity.Student;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("student.xml");
- Person kevin = ctx.getBean("kevin", Student.class);
- Person maomao = ctx.getBean("maomao", Student.class);
- System.out.println(maomao);
- System.out.println(kevin);
- }
- }
输出
信息: Loading xml bean definitions from class path resource [student.xml]
- Student{
- height=100, name='maomao'
- }
- Student{
- height=170, name='kevin'
- }
通过属性赋值
- Animal
- package com.kevin.spring.demo3.entity;
- /**
- * 动物
- */
- public class Animal {
- /**
- * 动物名称
- */
- private String name;
- public Animal() {
- }
- public Animal(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public String toString() {
- return "Animal{" +
- "name='" + name + '\'' +
- '}';
- }
- }
animal.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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="dog" class="com.kevin.spring.demo3.entity.Animal">
- <property name="name" value="dog"></property>
- </bean>
- <bean id="cat" class="com.kevin.spring.demo3.entity.Animal" p:name="cat"></bean>
- </beans>
测试
- package com.kevin.spring.demo3.test;
- import com.kevin.spring.demo3.entity.Animal;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * 测试类
- */
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("animal.xml");
- Animal dog = ctx.getBean("dog",Animal.class);
- Animal cat = ctx.getBean("cat",Animal.class);
- System.out.println(cat);
- System.out.println(dog);
- }
- }
输出结果
信息: Loading xml bean definitions from class path resource [animal.xml]
- Animal{
- name='cat'
- }
- Animal{
- name='dog'
- }
对象引用
- Tyre
- package com.kevin.spring.demo4.entity;
- /**
- * 轮胎
- * @author: kevin
- * @Date: 2018/12/8
- */
- public class Tyre {
- private String name;
- public Tyre(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public String toString() {
- return "Tyre{" +
- "name='" + name + '\'' +
- '}';
- }
- }
- Car
- package com.kevin.spring.demo4.entity;
- /**
- * 车
- */
- public class Car {
- private String name;
- private Tyre tyre;
- public Car(String name, Tyre tyre) {
- this.name = name;
- this.tyre = tyre;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Tyre getTyre() {
- return tyre;
- }
- public void setTyre(Tyre tyre) {
- this.tyre = tyre;
- }
- @Override
- public String toString() {
- return "Car{" +
- "name='" + name + '\'' +
- ", tyre=" + tyre +
- '}';
- }
- }
测试
- package com.kevin.spring.demo4.test;
- import com.kevin.spring.demo4.entity.Car;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("car.xml");
- Car bike = ctx.getBean("bike", Car.class);
- System.out.println(bike);
- }
- }
输出结果
信息: Loading xml bean definitions from class path resource [car.xml]
Car{name='bike', tyre=Tyre{name='自行车轮胎'}}
对象作用域
在大多数情况下, 单例 bean 是很理想的方案. 初始化和垃圾回收对象实例所带来的的成本只留给一些小规模任务, 在这些任务中, 让对象保持无状态并且在应用中反复重用这些对象可能并不合理. 在这种情况下, 将 class 声明为单例的 bean 会被污染, 稍后重用的时候会出现意想不到的问题. -《spring 实战》
Spring 定义了多种作用域, 可以基于这些作用域创建 bean, 包括:
作用域 | 描述 |
---|---|
单例(Singleton) | 在整个应用中,只创建 bean 的一个实例 |
原型(Prototype) | 每次注入或者通过 spring 应用上下文获取的时候,都会创建一个新的 bean 实例 |
会话(Session) | 在 web 应用中,为每个会话创建一个 bean 实例 |
请求(Request) | 在 web 应用中,为每个请求创建一个 bean 实例 |
1,spring 中默认是单例的, 我们通过之前的代码演示下
- <?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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="dog" class="com.kevin.spring.demo3.entity.Animal">
- <property name="name" value="dog"></property>
- </bean>
- <bean id="cat" class="com.kevin.spring.demo3.entity.Animal" p:name="cat"></bean>
- </beans>
测试
- package com.kevin.spring.demo3.test;
- import com.kevin.spring.demo3.entity.Animal;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * 测试类
- */
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("animal.xml");
- Animal dog1 = ctx.getBean("dog",Animal.class);
- Animal dog2 = ctx.getBean("dog",Animal.class);
- System.out.println(dog1 == dog2);
- }
- }
输出结果
true
这样验证了从容器中取回的对象默认是单例的.
2, 设置成 Prototype
- <?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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="dog" class="com.kevin.spring.demo3.entity.Animal" scope="prototype">
- <property name="name" value="dog"></property>
- </bean>
- <bean id="cat" class="com.kevin.spring.demo3.entity.Animal" p:name="cat"></bean>
- </beans>
测试
- ApplicationContext ctx = new ClassPathXmlApplicationContext("animal.xml");
- Animal dog1 = ctx.getBean("dog",Animal.class);
- Animal dog2 = ctx.getBean("dog",Animal.class);
- System.out.println(dog1 == dog2);
输出结果
false
延迟初始化 bean
ApplicationContext 实现的默认行为是在启动时将所有的 singleton bean 提前进行实例化. 这样配置中或者运行环境的错误就会立刻发现. 如果你想延迟初始化. 可以在 xml 中进行配置
- <bean id="kevin" class="com.kevin.spring.demo2.entity.Student" lazy-init="true">
- <constructor-arg name="name" value="kevin"></constructor-arg>
- <constructor-arg name="height" value="170"></constructor-arg>
- </bean>
测试
- public static void main(String[] args) throws InterruptedException {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("student.xml");
- Thread.sleep(3000);
- Person kevin = ctx.getBean("kevin", Student.class);
- System.out.println(kevin);
- }
大家自己运行后发现, 确实并不是启动后就加载的.
回调方法
- Student
- public void init() {
- System.out.println("执行 init 方法");
- }
- public void over() {
- System.out.println("执行 over 方法");
- }
student.xml
- <bean id="kevin" class="com.kevin.spring.demo2.entity.Student" lazy-init="true" init-method="init" destroy-method="over">
- <constructor-arg name="name" value="kevin"></constructor-arg>
- <constructor-arg name="height" value="170"></constructor-arg>
- </bean>
测试方法
- public static void main(String[] args) throws InterruptedException {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("student.xml");
- Thread.sleep(3000);
- Person kevin = ctx.getBean("kevin", Student.class);
- System.out.println(kevin);
- }
输出结果
Student 初始化
执行 init 方法
Student{height=170, name='kevin'}
本篇文章暂时先介绍到这里, 天气真的很冷, 没有暖气, 冻死我的手了. 好了, 玩的开心!
完整代码: https://github.com/runzhenghengbin/spring-study/tree/master/spring-demo01
参考: https://www.cnblogs.com/best/p/5727935.html
来源: https://www.cnblogs.com/zhenghengbin/p/10087889.html