当前位置: 首页 > news >正文

Spring 的创建和日志框架的整合

目录

一、第一个 Spring 项目

1、配置环境

2、Spring 的 jar 包

Maven 项目导入 jar 包和设置国内源的方法:

3、Spring 的配置文件

4、Spring 的核心 API

ApplicationContext

4、程序开发

5、细节分析

(1)名词解释

(2)Spring 工厂的相关方法

(3)配置文件中的细节

1、只配置 class 属性

2、name 属性

6、Spring 工厂的底层实现原理(简易版) 

7、思考

二、Spring 与 日志框架的整合

1、Spring 如何整合日志框架?


一、第一个 Spring 项目

1、配置环境


2、Spring 的 jar 包

在项目的 porm.xml 中添加 Spring 框架的支持,xml 配置如下:

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

复制的时候注意观察当前的 pom.xml 中是否已经有 dependices

如果 jar 包下载过慢或者下载失败,我们可以设置国内源来解决 

Maven 项目导入 jar 包和设置国内源的方法:

1、打开自己的 idea 检测 maven 的配置是否正确

这两个地方都要进行配置!!!

然后设置 settings 文件:


<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0https://maven.apache.org/xsd/settings-1.0.0.xsd"><mirrors><mirror>  <id>alimaven</id>  <name>aliyun maven</name>  <url>http://maven.aliyun.com/nexus/content/groups/public/</url>  <mirrorOf>central</mirrorOf>          </mirror>  </mirrors>
</settings>

如果电脑中没有 settings 文件,就自己创建一个,如果有,就直接在原来的 settings 文件上更改就行

2、如果继续出错,就删除本地 maven 仓库的 jar 包重新下载

3、当前网络运营商有问题,就尝试更换链接的数据源,使用更好的网络,如果还是不行,就间隔一段时间之后再去尝试


3、Spring 的配置文件

1、配置文件的放置位置:任意位置,没有硬性要求

2、配置文件的命名:没有硬性要求,建议叫  applicationContext.xml

接下来,我们思考一个问题:

Spring 框架如何知道开发人员未来会把配置文件放在哪里,叫什么名字呢?

所以,日后应用 Spring 框架时,需要进行配置文件路径的设置

按照图中步骤,在 resourses 下创建好一个文件,并按照建议给它命名为 applicationContext.xml

此时我们就会发现,整个 Spring 的配置文件就帮我们建好了,


4、Spring 的核心 API

ApplicationContext

作用:Spring 提供的 ApplicationContext 这个工厂,主要的作用就是用于对象的创建

好处:解耦合

ApplicationContext 是一个接口类型

接口的主要目的:屏蔽实现的差异(工厂可能会应用到不同的开发场景下,不同的开发场景有不同的特点)

Spring 主要提供两种类型的工厂:

1、非 web 环境:ClassPathXmlApplicationContext(main,junit)

2、web 环境:XmlWebApplicationContext

我们称 ApplicationContext 是一个重量级资源

那么什么是一个重量级资源?

如果一个对象对内存占用的比较多,那么我们就称之为重量级资源

这也就意味着,ApplicationContext 这个工厂的对象,会占用大量的内存

正因为它的内存占用比较多,所以我们不会频繁的创建对象:一个应用只会创建一个工厂对象

也正是因为它有这样的特点,所以这个对象就有可能会出现并发访问(多线程访问)的情况

所以,ApplicationContext 工厂,一定是线程安全的(多线程并发访问)


4、程序开发

Spring 提供的工厂和我们自己写的工厂,本质上是没有差异的,都是解耦合的

那么,对于 Spring 来讲,它的工厂使用,和我们前面所总结的通用工厂的使用方式,本质上是没有区别的

1、创建类型

2、配置文件的配置 applicationContext.xml

3、通过工厂类,获得对象 ApplicationContext

1、创建类型

2、配置文件的配置

我们要在 beans 下面创建一个子标签,里面有两个属性:id 和 class

id 属性:就是起个名字,命名(唯一的)

class 属性:配置所需要创建的文件的全限定名

虽然组织形式不同,但是所需要的要素是完全一样的

通过这步,我们也告诉了 Spring ,需要生产 Person 对象

3、通过工厂类,获得对应的对象

        //用于测试 Spring 的第一个程序public static void test() {//1、获得 Spring 工厂ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");//2、通过工厂类来获得对象Person person = (Person) ctx.getBean("person");System.out.println("person = " + person);}

此时,我们会发现,这个对象的引用打印出来了

说明这个对象由 Spring 的工厂创建完成了


5、细节分析

(1)名词解释

Spring 工厂创建的对象,叫做 bean 或者 组件(componet)


(2)Spring 工厂的相关方法

//通过这种⽅式获得对象,就不需要强制类型转换
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);//当前Spring的配置⽂件中 只能有⼀个<bean class是Person类型
Person person = ctx.getBean(Person.class);
System.out.println("person = " + person);//获取的是 Spring⼯⼚配置⽂件中所有bean标签的id值 
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {System.out.println("beanDefinitionName = " +
beanDefinitionName);
}//根据类型获得Spring配置⽂件中对应的id值
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {System.out.println("id = " + id);
}//⽤于判断是否存在指定id值得bean
if (ctx.containsBeanDefinition("a")) {System.out.println("true = " + true);
}else{System.out.println("false = " + false);
}//⽤于判断是否存在指定id值得bean
if (ctx.containsBean("person")) {System.out.println("true = " + true);
}else{System.out.println("false = " + false);
}

(3)配置文件中的细节

1、只配置 class 属性

<bean class="Person"/>

上述这种配置,有没有 id 值呢?

我们可以借助上面的 ctx.getBeanDefinitionNames(); 来进行观察

我们发现,spring 会自动生成一个 id 的默认值,所以我们没有给它设定 id ,但是实际上还是存在一个 id 与之对应的

应用场景:如果这个 bean 只需要使用一次,那么就可以省略 id 值,反之,如果这个 bean 会使用多次或者被其它 bean 引用,则需要设置 id 值

2、name 属性

用于在 Spring 的配置文件中,为 bean 对象定义别名(小名)

<bean id="person1" name="p" class="Person" ></bean>

id 与 name 相同点:

1、ctx.getBean(" id | name ") ; 都可以获取到对象

2、 < bean id = " " class = " " > 和 < bean name = " " class = " " >二者是等效的

id 和 name 的区别:

1、别名可以定义多个,但是 id 只能是一个

2、XML 的 id 属性的值,命名的时候要求:必须要以字母开头,字母,数字,下划线,连字符,不能以特殊字符开头,比如 / ,而 name 属性的值,在命名的时候,是没有要求的,所以 name 属性会应用在特殊命名的场景下,但是 xml 发展到了今天,id 的属性的限制,已经不存在了

3、代码的区别

//⽤于判断是否存在指定id值得bean,不能判断name值if (ctx.containsBeanDefinition("person")) {System.out.println("true = " + true);}else{System.out.println("false = " + false);}//⽤于判断是否存在指定id值得bean,也可以判断name值if (ctx.containsBean("p")) {System.out.println("true = " + true);}else{System.out.println("false = " + false);}

6、Spring 工厂的底层实现原理(简易版) 

反射的底层是否会调用构造方法呢?

虽然反射创建了对象,但是底层也一定会调用这个对象的构造方法(无参),所以我们也可以认为反射创建对象就等效于我们的 new 创建对象

如果这个构造方法是私有的怎么办呢?

private 修饰的只能在本类调用,而显然 String 是外类

通过代码实验,我们能发现,即使构造方法被设为了私有的,private 的构造方法依旧会被调用

底层还是通过反射来实现的,因为反射能够调用一个类的私有的属性和构造方法,所以 Spring 工厂是可以调用对象私有的构造方法来创建对象的


7、思考

未来在开发过程中,是不是所有的对象都会被交给 Spring 工厂来创建呢?

理论上来说,是的,但是有特例:实体对象(entity)

实体对象是不会交给 Spring 创建的,是由持久层框架来进行创建的。


二、Spring 与 日志框架的整合

Spring 与日志框架整合,日志框架就可以在控制台中输出 Spring 框架运行过程中的一些重要的信息

好处:便于我们了解 Spring 框架的运行过程,利于程序的调试

1、Spring 如何整合日志框架?

Spring 的不同版本,针对于日志框架的整合,以及整合的内容和方式,是有一些区别的

比如:Spring 1.2.3早期的日志框架,都是与 common-logging.jar 这个日志进行整合的

           Spring 5.x 默认整合的日志框架是 logback 或者 log4j2

根据我们的开发需要,我们想让 Spring 5.x 整合 log4j,那么整合 log4j 怎么整合呢?

1、引入 log4j 的 jar 包

2、引入 log4j.properties 配置文件

以 jar 包的方式,我们肯定要通过 maven 来完成,所以我们要设置我们的 pom 文件,那么在 pom 文件中我们要添加对应的依赖

<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version>
</dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

第二个配置就是引入 log4j.properties 的配置文件

# resources # resources⽂件夹根⽬录下
### ### 配置根
log4j.rootLogger = debug,console### ### ⽇志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

整合完毕之后再次运行代码,就能发现区别了:

我们会发现,当我们整合日志之后,我们从控制台中看到的内容就不仅仅基于我们打印的,还基于我们 spring 内部运行的

这样的话,在日后解决复杂性问题的时候,我们就可以通过日志,大概可以猜测到 Spring 帮我们做了什么,就更加利于我们后续程序的调试

相关文章:

Spring 的创建和日志框架的整合

目录 一、第一个 Spring 项目 1、配置环境 2、Spring 的 jar 包 Maven 项目导入 jar 包和设置国内源的方法&#xff1a; 3、Spring 的配置文件 4、Spring 的核心 API ApplicationContext 4、程序开发 5、细节分析 &#xff08;1&#xff09;名词解释 &#xff08;2&…...

11-集合和学生管理系统

1.ArrayList 集合和数组的优势对比&#xff1a; 长度可变添加数据的时候不需要考虑索引&#xff0c;默认将数据添加到末尾 1.1 ArrayList类概述 什么是集合 ​ 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以发生改变 ArrayList集合的特点 ​ 长度可以变化…...

C语言进阶指针(3) ——qsort的实现

大家好&#xff0c;我们今天来学习回调函数qsort的实现。 首先让我们打开cplusplus.com找到qsort函数。 我们看到这个函数就可以看到它的头文件和参数信息。 #include<stdlib.h> void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const voi…...

Rust源码分析——Rc 和 Weak 源码详解

Rc 和 Weak 源码详解 一个值需要被多个所有者拥有 rust中所有权机制在图这种数据结构中&#xff0c;一个节点可能被多个其它节点所指向。那么如何表示图这种数据结构&#xff1f;在多线程中&#xff0c;多个线程可能会持有同一个数据&#xff1f;如何解决这个问题。 Rc rus…...

【网络编程】深入理解TCP协议二(连接管理机制、WAIT_TIME、滑动窗口、流量控制、拥塞控制)

TCP协议 1.连接管理机制2.再谈WAIT_TIME状态2.1理解WAIT_TIME状态2.2解决TIME_WAIT状态引起的bind失败的方法2.3监听套接字listen第二个参数介绍 3.滑动窗口3.1介绍3.2丢包情况分析 4.流量控制5.拥塞控制5.1介绍5.2慢启动 6.捎带应答、延时应答 1.连接管理机制 正常情况下&…...

社区团购商城小程序v18.1开源独立版+前端

新增后台清理缓存功能 修复定位权限 修复无法删除手机端管理员 11月新登录接口修复&#xff01; 修复商家付款到零钱&#xff0c; 修复会员登陆不显示头像&#xff0c; 修复无法修改会员开添加绑定...

MATLAB入门-字符串操作

MATLAB入门-字符串操作 注&#xff1a;本篇文章是学习笔记&#xff0c;课程链接是&#xff1a;link MATLAB中的字符串特性&#xff1a; 无论是字符还是字符串&#xff0c;都要使用单引号来‘’表示&#xff1b;在MATLAB中&#xff0c;字符都是在矩阵中存储的&#xff0c;无论…...

Kong Learning

一、Kong Kong是由Mashape公司开源的可扩展的Api GateWay项目。它运行在调用Api之前&#xff0c;以插件的扩展方式为Api提供了管理。比如&#xff0c;鉴权、限流、监控、健康检查等&#xff0c;Kong是基于lua语言、nginx以及openResty开发的&#xff0c;所有拥有动态路由、负载…...

Python怎样写桌面程序

要编写Python桌面应用程序&#xff0c;可以使用以下几种方法&#xff1a; 1.使用Tkinter模块&#xff1a;Tkinter是Python自带的GUI工具包之一&#xff0c;可以使用它来创建基本的GUI界面。例如&#xff0c;可以创建一个简单的窗口&#xff0c;添加按钮、文本框等控件&#xf…...

蓝桥杯2023年第十四届省赛真题-平方差--题解

蓝桥杯2023年第十四届省赛真题-平方差 时间限制: 3s 内存限制: 320MB 提交: 2379 解决: 469 题目描述 给定 L, R&#xff0c;问 L ≤ x ≤ R 中有多少个数 x 满足存在整数 y,z 使得 x y2 − z2。 输入格式 输入一行包含两个整数 L, R&#xff0c;用一个空格分隔。 输出格…...

iText实战--根据绝对位置添加内容

3.1 direct content 概念简介 pdf内容的4个层级 层级1&#xff1a;在text和graphics底下&#xff0c;PdfWriter.getDirectContentUnder() 层级2&#xff1a;graphics层&#xff0c;Chunk, Images背景&#xff0c;PdfPCell的边界等 层级3&#xff1a;text层&#xff0c;Chun…...

使用navicat for mongodb连接mongodb

使用navicat for mongodb连接mongodb 安装navicat for mongodb连接mongodb 安装navicat for mongodb 上文mongodb7.0安装全过程详解我们说过&#xff0c;在安装的时候并没有勾选install mongodb compass 我们使用navicat去进行可视化的数据库管理 navicat for mongodb下载地址…...

Qt ffmpeg音视频转换工具

Qt ffmpeg音视频转换工具&#xff0c;QProcess方式调用ffmpeg&#xff0c;对音视频文件进行格式转换&#xff0c;支持常见的音视频格式&#xff0c;主要在于QProcess的输出处理以及转换的文件名和后缀的处理&#xff0c;可以进一步加上音视频剪切合并和音视频文件属性查询修改的…...

机器学习笔记 - 视频分析和人类活动识别技术路线简述

一、理解人类活动识别 首先了解什么是人类活动识别,简而言之,是对某人正在执行的活动/动作进行分类或预测的任务称为活动识别。 我们可能会有一个问题:这与普通的分类任务有什么不同?这里的问题是,在人类活动识别中,您实际上需要一系列数据点来预测正确执行的动作。 看看…...

Redis从入门到精通(三:常用指令)

前边我们介绍了redis存储的四种基本数据类型&#xff0c;并纵向介绍了这四种数据类型的各种指令操作&#xff0c;现在我们这个章节从横向来总结一下关于key的常用指令和数据库常用指令 key常用指令 删除指定key del key 获取key是否存在 exists key 获取key的类型 type …...

代码随想录day39 || 动态规划 || 不同路径

62.不同路径 ● 力扣题目链接 ● 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 ● 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 ● 问总共有…...

电商平台API接口采集电商平台淘宝天猫京东拼多多数据获取产品详情信息,销量,价格,sku案例

淘宝SKU详情接口是指&#xff0c;获取指定商品的SKU&#xff08;Stock Keeping Unit&#xff0c;即库存量单位&#xff09;的详细信息。SKU是指提供不同的商品参数组合的一个机制&#xff0c;通过不同的SKU来标识商品的不同组合形式&#xff0c;如颜色、尺寸等。SKU详情接口可以…...

The ‘<‘ operator is reserved for future use. 错误解决

The < operator is reserved for future use. 错误解决 在 PowerShell 终端执行 python learnstock.py < ldata.txt 发生错误&#xff0c; The < operator is reserved for future use.解决方法&#xff0c; cmd /c python learnstock.py < ldata.txt完结&#x…...

vulnhub靶机Thoth-Tech

下载地址&#xff1a;https://download.vulnhub.com/thothtech/Thoth-Tech.ova 主机发现 arp-scan -l 目标&#xff1a;192.168.21.148 端口扫描 nmap --min-rate 10000 -p- 192.168.21.148 服务扫描 nmap -sV -sT -O -p21,22,80 192.168.21.148 漏洞扫描 nmap --scriptvu…...

不可思议,无密码登录所有网站!

hello&#xff0c;我是小索奇 居然可以免密码登录你的网站&#xff1f;听起来是不是很恐怖 确实如此&#xff0c;Cookie可以用于保持用户在网站上的登录状态&#xff0c;从而实现 免密码登录&#xff0c;学会了不要做坏事哈 这里仅做免密码登录的实操&#xff0c;就不介绍Cooki…...

深度学习编译器关键组件

1 高层中间代码 为了克服传统编译器中采用的IR限制DL模型中复杂计算的表达的局限性&#xff0c;现有的DL编译器利用高层IR&#xff08;称为图IR&#xff09;进行高效的代码优化设计。 1.1 图表示 基于DAG的IR&#xff1a;基于DAG的IR是编译器构建计算图的最传统方法之一&…...

【C++】string类模拟实现下篇(附完整源码)

目录 1. resize2. 流插入<<和流提取>>重载2.1 流插入<<重载2.2 流提取 << 3. 常见关系运算符重载4. 赋值重载4.1浅拷贝的默认赋值重载4.2 深拷贝赋值重载实现4.3 赋值重载现代写法 5. 写时拷贝(了解&#xff09;6.源码6.1 string.h6.2 test.cpp 1. res…...

Android高级开发-APK极致优化

九道工序 1. SVG(Scalable Vector Graphics)可缩放矢量图 使用矢量图代替位图可以减小 APK 的尺寸&#xff0c;因为可以针对不同屏幕密度调整同一文件的大小&#xff0c;而不会降低图像质量。 矢量图首次加载时可能消耗更多的 CPU 资源。之后&#xff0c;二者的内存使用率和…...

Rocketmq--消息驱动

1 MQ简介 1.1 什么是MQ MQ&#xff08;Message Queue&#xff09;是一种跨进程的通信机制&#xff0c;用于传递消息。通俗点说&#xff0c;就是一个先进先出的数据结构。 1.2 MQ的应用场景 1.2.1 异步解耦 最常见的一个场景是用户注册后&#xff0c;需要发送注册邮件和短信通…...

华为云云耀云服务器L实例评测|centos系统搭建git私服

搭建git私服 前言一、华为云云耀云服务器L实例租用二、华为云云耀云服务器L实例安装git三、华为云云耀云服务器L实例git配置1.创建文件用于存放公钥2.设置文件权限3.配置本地公钥 四、华为云云耀云服务器L实例部署git仓库四、git仓库到本地总结 前言 之前一直想搭建一个属于自…...

苹果CMS主题 MXonePro二开优化修复开源版影视网站源码

MXPro模板主题(又名&#xff1a;mxonepro)是一款基于苹果cms程序的一款全新的简洁好看UI的影视站模板类似于西瓜视频&#xff0c;不过同对比MxoneV10魔改模板来说功能没有那么多,也没有那么大气&#xff0c;但是比较且可视化功能较多简洁且有周更记录样式等多功能后台设置&…...

【新版】系统架构设计师 - 软件架构设计<轻量级架构>

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 软件架构设计&#xff1c;轻量级架构&#xff1e;考点摘要轻量级架构表示层业务逻辑层持久层数据库 SSH与SSMORMHibernate与Mybatis 架构 - 软件架构设计&#xff1c;轻量级架构&#xff1e; 考点…...

系统架构设计专业技能 ·结构化需求分析 - 数据流图

现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 点击进入系列文章目录 系统架构设计高级技能 结构化需求分析 - 数据流图 一、数据流图的基本概念二、需…...

linux内核分析:线程和进程创建,内存管理

lec18-19:进程与线程创建 lec20-21虚拟内存管理 内核代码,全局变量这些只有一份,但是内核栈有多份,这可能就是linux线程模型1对1模式的由来。通过栈来做的 x86 CPU支持分段和分页(平坦内存模式)两种 分段,选择子那里就有特权标记了...

SpringMvc根据返回值类型不同处理响应

目录 一、介绍 二、返回值为void &#xff08;1&#xff09;控制层方法 三、返回值为String &#xff08;1&#xff09;控制层 四、返回值为ModelAndView &#xff08;1&#xff09;控制层方法 &#xff08;2&#xff09;jsp页面 一、介绍 我们可以通过控制器方法的返回…...

个体户 做网站/网站如何快速被百度收录

Yii的webservice是强大的&#xff0c;但是官方文档太垃圾&#xff0c;Api看了和没看一样&#xff0c;百度google的搜索提供不了任何帮助。所以我一定要记录下来&#xff0c;好让后来者不再浪费时间探索。首先&#xff0c;跟着官方文档一步步走&#xff0c;你肯定可以写出你的we…...

广东深广东深圳网站建设服务/手机打开国外网站app

点击上方蓝色字体&#xff0c;选择“标星公众号”优质文章&#xff0c;第一时间送达上一篇&#xff1a;这300G的Java资料是我师傅当年给我的&#xff0c;免费分享给大家&#xff08;已修复&#xff09;下一篇&#xff1a;昨天分享资料不小心把百度网盘深处的秘密泄露了&#xf…...

北京网站设计公司哪儿济南兴田德润简介/南京seo排名扣费

2019独角兽企业重金招聘Python工程师标准>>> 今天查JS的一些框架&#xff0c;无意进入了一个网站http://www.w3cschool.cc/。浏览了一下之后&#xff0c;发现真是。。棒极了&#xff01;&#xff01;这个网站提供了多种语言和框架的入门教程&#xff0c;内容很丰富&…...

辽宁省建设工程招标协会网站/广州:推动优化防控措施落地

一些知识点&#xff1a; 要将session进行持久化&#xff1a; 要将cookie进行持久化&#xff0c;则要将cookie中的JSSESSIONID进行持久化。这里要创建一个cookie来覆盖服务器之前自动生成的JSSESSIONID。 这里分为添加进购物车&#xff0c;查看购物车&#xff0c;和前端 前端…...

怎样做网站手机和电脑通用/广州百度搜索排名优化

星期日星期一星期二星期三星期四星期五星期六 所花时间 &#xff08;包括上课&#xff09; 8:00~9:50 9:30~10&#xff1a;30代码量&#xff08;行&#xff09; 206&#xff08;不包括复制例子&#xff09;博客量&#xff08;篇&#xff09;  1…...

做动画网站去哪采集/中国最厉害的营销策划公司

本文地址&#xff1a;http://www.cnblogs.com/archimedes/p/win-tc-graphics-use.html&#xff0c;转载请注明源地址。 由于最近接到一个紧急任务&#xff0c;需要实现一个程序&#xff0c;显示一些分形几何中的图形&#xff0c;例如&#xff1a;Koch曲线 感觉java的swing的界面…...