spring学习总结(一)_Ioc基础(上)

综合技术 2018-12-08 阅读原文

最近经历了许许多多的事情,学习荒废了很久。自己的目标成了摆设。现在要奋起直追了。最近发现了张果的博客。应该是一个教师。看了他写的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

博客园精华区

责编内容by:博客园精华区阅读原文】。感谢您的支持!

您可能感兴趣的

朱晔和你聊Spring系列S1E3:Spring咖啡罐里的豆子... 标题中的咖啡罐指的是Spring容器,容器里装的当然就是被称作Bean的豆子。本文我们会以一个最基本的例子来熟悉Spring的容器管理和扩展点。 阅读PDF版本 为什么要让容器来管理对象? 首先我们来聊聊这个问题,为什么...
如何在优雅地Spring 中实现消息的发送和消费... 本文将对rocktmq-spring-boot的设计实现做一个简单的介绍,读者可以通过本文了解将RocketMQ Client端集成为spring-boot-starter框架的开发细节,然后通过一个简单的示例来一步一步的讲解如何使用这个s...
原 荐 利用Lombok编写优雅的spring依赖注入代码,去掉繁人的@Autowired... HeyS1的个人页面 效率工具 正文 利用Lombok编写优雅的spring依赖注入代码,去掉繁人的@Autowired 原 ...
【死磕 Spring】—– IOC 之 IOC 初始化总结... 前面 13 篇博文从源码层次分析了 IOC 整个初始化过程,这篇就这些内容做一个总结将其连贯起来。 在前文提过,IOC 容器的初始化过程分为三步骤:Resource 定位、BeanDefinition 的载入和解析,BeanDefini...
Spring源码分析:AOP源码解析(下篇) AspectJAwareAdvisorAutoProxyCreator及为Bean生成代理时机分析 上篇文章说了,org.springframework.aop.aspectj.autoproxy.AspectJAwareAdv...