[From Zero]全手动搭建第一个Spring程序

前言

在使用Java开发时,经常是打开一个IDE,然后按着固定的步骤新建项目,写一些代码,编译运行。而且现在的IDE越来越智能,有些甚至按几个按钮就可以开始写代码了,导致我们都不知道为什么需要配置这些选项,以及为什么配置了这些选项。虽然不要重复造轮子,而且IDE大大提高了开发效率,但是离开了IDE,都不再会编程了,所以基本的知识,还是必要学习下。

在使用Spring开发时,我们会有各种这样的jar包,各种配置文件,而且Spring中实现控制反转(IOC)的依赖注入(DI)也离不开这些配置。但是为什么是这样的,一直不理解,下面结合w3cSchool中的Spring教程,全手动搭建第一个Spring程序。

各位看官,如有错误,还望告知,不甚感激!

参考:1,https://www.w3cschool.cn/wkspring/dgte1ica.html

正文

前置条件:

1、已安装配置java环境,这里使用java版本为jdk1.8

2、下载Spring 库,这里使用Spring版本为5.0.8.RELEASE

3、下载Apache Commons Logging API,这里使用的版本为1.2,(开始不知道为什么要用这个包,理解上只是运行一个helloworld好像不需要,查了一下,因为spring的内部实现中使用commons-logging,见https://www.w3cschool.cn/wkspring/dcu91icn.html

步骤:

一、建立工作目录

一般一个java项目相关的文件都会放在一个工作目录,并在其中建立子文件夹来存放相关类型的文件。这里建立一个工作目录(在IDE中一般是称为项目路径),并在其中建立src目录(用于存放源码),libs目录(用于存放外部jar包),resources目录(用于存放静态资源文件,包括xml配置文件),classes目录(用于存放编译生成的字节码文件)。如下图

二、编写源文件

IDE只是作为一种工具,这里手动搭建Spring程序,在src目录下建立两个文件(可以使用Notepad++),分别命名为HelloWorld.java和MainApp.java。文件内容来源于参考1,如下:

HelloWorld.java

package org.wufeipeng;

// 一个简单的Java Bean
public class HelloWorld {
    private String message;
    public void setMessage(String message){
        this.message  = message;
    }
    // 调用这个方法会打印出message
    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}

MainApp.java

package org.wufeipeng;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

// 主程序
public class MainApp {
    public static void main(String[] args) {
        // 读取classpath下的配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        // 获取Bean对象,上下文中的Bean都是Object类型的,需要强转
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
        // 执行对象的方法
        obj.getMessage();
    }
}

如上,建立源文件时并没有按package建立目录,这和IDE中建立package时的结果是不同的,我觉得最开始的搞java开发肯定也没有想这么多。按着最原始的做法,但是在源文件中还是得分包(也就是最上面那一句package  ***.***;),如果不分包,如今版本的jdk编译时会报错。

同时还要新建一个xml配置文件,用来注入Bean,内容如下:

Beans.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">

    <!-- 定义一个Java Bean,并为其属性赋值 -->
    <bean id="helloWorld" class="org.wufeipeng.HelloWorld">
        <property name="message" value="Hello World!"/>
    </bean>

</beans>

三、编译运行

将Spring的库文件和Apache logging的库文件拷贝到libs目录。打开命令行工具,首先切换到工作目录,然后进行按照Java程序运行方法进行编译和运行。最开始我将所有Spring的jar包都拷到libs目录,但是,肯定不是所有jar包都需要的,为了试验到底哪些jar有用,编译运行了多次。经过试验,在编译时使用以下命令就可以编译成功,下面多个classpath的路径之间需要用分隔符,Windows环境用;分割,在Linux环境用:分割。

> javac -d .\classes -classpath .\libs\spring-beans-5.0.8.RELEASE.jar;.\libs\spring-context-5.0.8.RELEASE.jar;.\libs\spring-core-5.0.8.RELEASE.jar .\src\*.java

> javac -d .\classes -classpath .\libs\spring-beans-5.0.8.RELEASE.jar;.\libs\spring-context-5.0.8.RELEASE.jar;.\libs\spring-core-5.0.8.RELEASE.jar -encoding utf-8 .\src\*.java

一共需要3个包:spring-beans-5.0.8.RELEASE.jar;spring-context-5.0.8.RELEASE.jar;spring-core-5.0.8.RELEASE.jar

解析:javac命令用于编译,-d选项指定编译类文件的目标目录(classes目录),-classpath设置用户类路径,它将覆盖 CLASSPATH 环境变量中的用户类路径,即将后面的三个jar包加到类路径,这样编译才能用到它们。.\src\*.java表示编译这个文件夹中所有.java文件。

编译成功,打开classes目录,会发现,虽然写源码没有按包建立目录结构,但是,编译之后还是会按照包建立目录结构。

在运行时,还得加上一些jar包以及目录,下面多个classpath的路径之间也需要分割,Windows环境用;分割,在Linux环境用:分割。

> java -classpath .\classes;.\resources;.\libs\spring-beans-5.0.8.RELEASE.jar;.\libs\spring-context-5.0.8.RELEASE.jar;.\libs\spring-core-5.0.8.RELEASE.jar;.\libs\commons-logging-1.2.jar;.\libs\spring-expression-5.0.8.RELEASE.jar org.wufeipeng.MainApp

> java -classpath .\classes;.\resources;.\libs\spring-beans-5.0.8.RELEASE.jar;.\libs\spring-context-5.0.8.RELEASE.jar;.\libs\spring-core-5.0.8.RELEASE.jar;.\libs\commons-logging-1.2.jar;.\libs\spring-expression-5.0.8.RELEASE.jar org.wufeipeng.MainApp

这里增加了两个包,commons-logging-1.2.jar,spring-expression-5.0.8.RELEASE.jar 。

解析:java命令用于运行class字节码文件,-classpath设置用户类路径,即将后面的classes目录,resource目录(因为要读取配置文件)和依赖的jar包加到类路径。org.wufeipeng.MainApp表示运行这个类,java class loader会根据这个全限定名在用户类路径中查找这个类来运行其main方法。

运行结果

 可见其中用Bean中的方法,成功打印出了xml文件中指定的message。

四、打成jar包运行

一般在运行java程序时,不可能将工作目录拷贝到各个地方运行,而是将编译好的文件打成jar包拷贝到其他路径运行。

首先将Beans.xml拷贝到classes文件夹中(这里就是classpath了),然后新建一个META-INF并在其中建立清单文件MANIFEST.MF。内容如下

MANIFEST.MF:

Manifest-Version: 1.0
Created-By: 1.8.0_152 (Oracle Corporation)
Main-Class: org.wufeipeng.MainApp
Class-Path: resources libs/spring-beans-5.0.8.RELEASE.jar libs/spring-context-5.0.8.RELEASE.jar libs/spring-core-5.0.8.RELEASE.jar libs/commons-logging-1.2.jar libs/spring-expression-5.0.8.RELEASE.jar

注意每一行的冒号(:)后面有个空格,Class-Path的各个值之间用空格分割,文件的最后要留空一行,也不知道为啥,很伤。

第一行标明了版本,第二行声明该文件的生成者,一般该属性是由jar命令行工具生成的,第三行定义jar文件的入口类,第四行标明类搜索路径。

运行打包命令:

> jar -cvfm hello-spring.jar META-INF\MANIFEST.MF -C classes .

> jar -cvfm hello-spring.jar META-INF\MANIFEST.MF -C classes .

注意最后一个点(.)

解析:jar命令用于打包class字节码文件,-c表示创建一个jar包,-f指定jar包的文件名,-v生成详细的报造,并输出至标准设备,即打印出打包过程,-m指定manifest.mf文件。后面指定了jar包名为hello-spring.jar,manifest.mf文件的路径。-C表示转到相应的目录下执行jar命令,即在classes目录下执行jar命令,因为我们现在在工作目录下,而jar命令需要在生成的class文件的目录中执行,最后还有一个点,表示以这里(classes)为起点以下的目录结构为包结构。

打包成功,jar包的结果如下

执行jar包

> java -jar hello-spring.jar

> java -jar hello-spring.jar

执行结果,和上面的结果相同。

小结

打包运行成功后还要几个问题:

1,以上命令在win7和win10环境的命令提示符中可以运行,但是在win10的PowerShell环境中报错,不知为何?

2,jar包的结构中没有第三方的jar包,在当前工作目录可以执行是因为目录下有libs子目录,而manifest.mf文件指定了其为类路径,当时拷贝到其他地方不能执行了,如何将第三方jar包放入jar包中,可以直接在任何环境运行jar文件?

分析:

上面main函数在运行时,首先使用使用配置文件类路径下的Beans.xml,生成了应用程序上下文,后面的ClassPathXmlApplicationContext很容易理解读取的是类路径下的Xml文件,在生成上下文过程中扫描配置文件,并生成相应的Beans,这里xml文件中定义了一个Bean,类型为org.wufeipeng.HelloWorld,通过id(helloworld)来标识这个Bean,并为这个类的属性message赋值Hello World。这句话就相当于

HelloWorld helloWorld = new HelloWorld();
helloWorld.setMessage("Hello World!");

而上下文context持有这个Bean,通过getBean("helloWorld")可以获得这个Bean,不过是Object类型的,因为其本身是HelloWorld类型,所以可以强转成功,然后调用其getMessage()方法,可以执行其中的方法,打印出Your Message : Hello World!

总结

 学习Spring的体系结构知道,Spring框架分为了以下这些内容,其中最核心的容器由spring-corespring-beansspring-contextspring-context-supportspring-expression(SpEL)构成,这刚好是编译的时候需要的几个包,而spring-context里面已经包含了spring-context-support的一些内容,理解中spring-expression主要是用来处理配置文件中的EL表达式的,所编译的时候没有读取配置文件,所以不需要,但是在运行的时候还是需要spring-expression

 简单记录下核心模块的功能:

  • spring-core模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。

  • spring-beans 模块提供 BeanFactory,工厂模式的微妙实现。

  • context模块建立在由core和 beans 模块的基础上建立起来的,它以一种类似于JNDI注册的方式访问对象。

  • spring-expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。

 它们完整的依赖关系

 这里可以解释为什么需要commons-logging。之所以没有引用spring-aop也可以正常运行,可能因为没有使用面向切面编程(AOP),也可能是因为spring-context包中已经有了相关的内容。

一个简单的程序,也可以折腾好多东西,特别是编译运行的阶段,查看了好多资料,慢慢才知道怎么用,后面有机会,还是得更加细致的看看。

——做一个明明白白的码农!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity 5 From Zero to Proficiency (Intermediate): A step-by-step guide to coding your first game in C# with Unity. Why this book can help you to get started with Game Development Creating your own game can be very intimidating at the start, and quite often, regardless of your experience with games, it is sometimes difficult to find the time and motivation to get over the first barriers and to get started. Often, these barriers seem higher than they actually are. Maybe you are a teacher trying to introduce games in your classroom or a parent trying to help your child with coding, but with no previous coding or game development experience; maybe you are a hobbyist who would love to create interactive environments based on your favorite games; maybe you are a student getting started with game development but you just don't know where to start or what resources to use; or maybe you have tried online video tutorials but found them disjointed. You may be wondering: "How can I start to create my games if I have no experience of coding", or "this game engine is so complex that I just don't know where to get started". This is quite common, and you can easily overcome these issues with a step-by-step approach that gets you to progressively develop and use your skills. This is the approach that I have used successfully over the past years to take students from no knowledge of coding or game development to good levels of proficiency in Unity and coding. Of course, it takes some time and dedication; however, by following the techniques and suggestions described in this book, I can promise you that you will progress, regardless of your background, and become more comfortable with Unity and coding. Content and structure of this book In this book, the third book in the series, you will become comfortable with programming in C# by creating a simple survival game in Unity. The book includes: A list of the learning objectives at the start of each chapter. Step-by-step activitie

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值