前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第1章: Spring 基础第1章:Spring 基础

第1章: Spring 基础第1章:Spring 基础

作者头像
zhuanxu
发布2018-08-23 13:08:10
2370
发布2018-08-23 13:08:10
举报
文章被收录于专栏:进击的程序猿进击的程序猿

第1章:Spring 基础

spring 简史

  1. xml配置 spring1.x,主要配置各种Bean
  2. 注解配置 spring2.x,基本配置用xml,业务配置用注解
  3. Java 配置 spring3.x,spring boot 都推荐使用 Java 配置

spring 概述

spring framework runtime
spring framework runtime

spring framework runtime

包括内容很多,每一块都能单独拿出来讲。

spring 在 idea 中的搭建

为了体验spring,所以建立的是一个 maven quick start 的项目,建立后的 pom.xml 配置如下:

代码语言:javascript
复制
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         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.wisely</groupId>
    <artifactId>highlight_spring5_idea</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>highlight_spring5_idea</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <!-- put your configurations here -->
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

spring 基础配置

spring 框架四大原则:

  1. 使用 POJO(Plain Old Java Object) 进行轻量级和最小侵入式开发
  2. 依靠依赖注入和接口实现松耦合
  3. 使用 AOP 和默认习惯进行声明式编程
  4. 使用 AOP 和模板减少代码冗余

依赖注入

依赖注入是通过配置+容器的方式实现的,配置可以通过 xml 配置、注解配置、java 配置实现,这些配置称为元配置数据,这些元配置本身不会有运行的能力,是通过程序解析代码后,根据元数据来做相应操作。

先介绍一个概念 Beans,Beans 是被 spring 容器管理的 POJO,Beans 以及 Beans 之间的依赖关系都是通过元数据来配置的,而这些元数据的使用方则是称为 IoC container 的容器。

Spring Framework 中 IoC container 主要代码是在 org.springframework.beansorg.springframework.context 两个包中。

在前面设置maven的依赖的时候,我们导入了 context, 看下依赖图:

dependence
dependence

dependence

可以看到org.springframework.context本身依赖于org.springframework.beans

IoC 容器具体到具体的类是BeanFactory,里面定义了基本的接口来获取 Beans,而ApplicationContext是为了企业级应用而对BeanFactory的一个扩展,具体可以看依赖图:

image_1bucpv7ih1nr81g9p1mfj14vv1kvlm.png-61.5kB
image_1bucpv7ih1nr81g9p1mfj14vv1kvlm.png-61.5kB

image_1bucpv7ih1nr81g9p1mfj14vv1kvlm.png-61.5kB

接口org.springframework.context.ApplicationContext的职责是负责Beans的实例化,配置,组装等工作,而这些对Beans的具体操作都是通过配置数据来控制的。因为ApplicationContext是一个接口,只要实现这个接口,就可以作为一个容器来使用,常用的容器有ClassPathXmlApplicationContextFileSystemXmlApplicationContext

下面是一个ApplicationContext工作的概括图:

image_1bucqalkp17dh13m9utv1ku71kfq13.png-10.1kB
image_1bucqalkp17dh13m9utv1ku71kfq13.png-10.1kB

image_1bucqalkp17dh13m9utv1ku71kfq13.png-10.1kB

ApplicationContext通过我们配置的元数据,棒我们实例化、配置好我们需要的Beans,当具体的一个ApplicationContext对象生成结束的时候,我们的系统也就做好运行的准备了。

元配置数据

配置有3类方式:xml、注解和java,我们此处主要讲xml。一个典型的xml配置文件结构如下:

代码语言:javascript
复制
<?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="..." class="...">
                <!-- collaborators and configuration for this bean go here -->
        </bean>

        <bean id="..." class="...">
                <!-- collaborators and configuration for this bean go here -->
        </bean>

        <!-- more bean definitions go here -->

</beans>

id 是对Bean的唯一标识,class则是具体的类名。

容器实例化

可以通过下面的代码得到一个具体的容器:

代码语言:javascript
复制
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

我们可以看到对于Beans的声明我们可以放到多个不同的xml文件中,还有另一个方式是在一个xml中导入其他的xml文件,如下:

代码语言:javascript
复制
<beans>
        <import resource="services.xml"/>
        <import resource="resources/messageSource.xml"/>

        <bean id="bean1" class="..."/>
        <bean id="bean2" class="..."/>
</beans>

Bean 概览

IoC 容器管理的Beans都是通过xml中<bean/>定义的,在IoC中这些定义被表示为BeanDefinition对象,包含的信息有:

  • bean 具体的实现类
  • bean 在 IoC 中的行为(scope, lifecycle callbacks 等)
  • bean 的依赖
  • bean 的其他配置信息

下面是一个具体属性和作用:

image_1bud0pssh19lt1kh0vgc1sb4ugj9.png-79.8kB
image_1bud0pssh19lt1kh0vgc1sb4ugj9.png-79.8kB

image_1bud0pssh19lt1kh0vgc1sb4ugj9.png-79.8kB

name

一个Bean可以有多个名字,也可以没有名字,在xml中可以通过id or name来指定,id只能指定唯一一个名字,name可以通过","或者";"或者空格将多个名字隔开,另一种指定名字的方式是通过alias,如下:

代码语言:javascript
复制
<alias name="fromName" alias="toName"/>

如果我们没有指定id或者name,IoC容器会自动生成一个名字。

对于不指定名字的使用场景是:inner beans 和 autowiring collaborators,后面介绍。

实例化

实例化一个Bean的方式有两种

  • 通过反射获取构造函数
  • 静态工厂

先看第一种,构造函数的方式。

构造函数的方式一般要求Bean有个默认的构造函数(没有任何参数),然后通过set方式来设置Bean的属性,配置如下:

代码语言:javascript
复制
<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

如果构造函数需要一些依赖注入,稍后介绍怎么完成。

另外一种方式是静态工厂,看配置:

代码语言:javascript
复制
<bean id="clientService"
        class="examples.ClientService"
        factory-method="createInstance"/>
        
public class ClientService {
        private static ClientService clientService = new ClientService();
        private ClientService() {}

        public static ClientService createInstance() {
                return clientService;
        }
}        

另一种工厂是来自于另一个Bean的方法

代码语言:javascript
复制
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="clientService"
        factory-bean="serviceLocator"
        factory-method="createClientServiceInstance"/>
        
public class DefaultServiceLocator {

        private static ClientService clientService = new ClientServiceImpl();

        public ClientService createClientServiceInstance() {
                return clientService;
        }
}        

依赖关系

依赖注入的种类

常见的依赖注入有构造函数注入和set方法注入,先来看构造函数注入。 构造函数注入 假设我们有下面的类:

代码语言:javascript
复制
package x.y;

public class Foo {

        public Foo(Bar bar, Baz baz) {
                // ...
        }
}

我们可以配置下面的xml,通过标签<constructor-arg/>来指定:

代码语言:javascript
复制
<beans>
        <bean id="foo" class="x.y.Foo">
                <constructor-arg ref="bar"/>
                <constructor-arg ref="baz"/>
        </bean>

        <bean id="bar" class="x.y.Bar"/>

        <bean id="baz" class="x.y.Baz"/>
</beans>

另外一种是构造函数依赖的是普通的类型,如int,String等,看例子:

代码语言:javascript
复制
package examples;

public class ExampleBean {

        // Number of years to calculate the Ultimate Answer
        private int years;

        // The Answer to Life, the Universe, and Everything
        private String ultimateAnswer;

        public ExampleBean(int years, String ultimateAnswer) {
                this.years = years;
                this.ultimateAnswer = ultimateAnswer;
        }
}

此时参数不再是Bean了,我们通过type,value的方式实现:

代码语言:javascript
复制
<bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg type="int" value="7500000"/>
        <constructor-arg type="java.lang.String" value="42"/>
</bean>

也可以通过index-value的方式:

代码语言:javascript
复制
<bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg index="0" value="7500000"/>
        <constructor-arg index="1" value="42"/>
</bean>

另外一种是在开启debug模式下使用的name-value,

代码语言:javascript
复制
<bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg name="years" value="7500000"/>
        <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

当然不想开启debug,也可以通过java的注释@ConstructorProperties来做:

代码语言:javascript
复制
package examples;

public class ExampleBean {

        // Fields omitted

        @ConstructorProperties({"years", "ultimateAnswer"})
        public ExampleBean(int years, String ultimateAnswer) {
                this.years = years;
                this.ultimateAnswer = ultimateAnswer;
        }
}

下面总结下依赖解析的整个过程:

  1. ApplicationContext创建并且读取元配置信息生成BeanDefinition对象
  2. 对于每个Bean,其依赖通过properties,constructor arguments ,static-factory method来声明的。
  3. 每个properties,constructor arguments是以值的形式或者对其他Bean的引用提供的。
  4. 每个properties,constructor arguments如果是值的话,能自动转换到对应的类型(int,long,boolean等)。

下一篇将会详细介绍下依赖。

更好的阅读体验可以看 https://www.zybuluo.com/zhuanxu/note/943431

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.11.08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第1章:Spring 基础
    • spring 简史
      • spring 概述
        • spring 在 idea 中的搭建
          • spring 基础配置
            • 依赖注入
            • 元配置数据
            • 容器实例化
          • Bean 概览
            • name
            • 实例化
          • 依赖关系
            • 依赖注入的种类
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档