基于java的汽车租赁系统的设计与实现,源码+论⽂
基于 java 的汽车租赁系统的设计与实现,源码+论⽂。
毕业设计题⽬:基于java的汽车租赁系统的设计与实现 压缩⾥⾯有:代码, 论⽂, 英⽂翻译,说明(对开发⼯具啊,tomcat什么的,还有mysql的具体说明,以及配置) 虽然,代码可能有那么⼀点瑕疵,但是可以运⾏。
JAVA 汽车租赁系统
⾮常全。
⽂件下载:
以下内容⽆关:
-------------------------------------------分割线---------------------------------------------
IOC概念 
  控制反转(Inversion of Control,IOC),是⾯向对象编程中的⼀种设计原则,它建议将不需要的职责
移出类,让类专注于核⼼职责,从⽽提供松散耦合,提⾼优化软件程序设计。它把传统上由程序代码直接操控的对象的调⽤权(new、get等操作对象)交给容器,通过容器来实现对象组件的装配和管理,也就是对组件对象控制权的转移,从程序代码本⾝转移到了外部容器。
IOC的实现⽅式
  IOC有多种实现⽅式,其中最常见的叫做“依赖注⼊”(Dependency Injection,简称DI),另外还有“依赖查”(Dependency Lookup),其中“依赖查”可分为“依赖拖拽”(Dependency Pull)和“上下⽂依赖查”(Contextualized Dependency Lookup)。
依赖的理解
  什么是依赖呢?Java开发是⾯向对象编程,⾯向抽象编程容易产⽣类与类的依赖。看下⾯的代码中,UserManagerImpl 类中有个对象属性 UserDao ,也就是说 UserManagerImpl 依赖 UserDao。也就是说,⼀个类A中有了类B的对象属性或类A的构造⽅法需要传递类B 对象来进⾏构造,那表⽰类A依赖类B。
public class UserManagerImpl implements UserManagerServie{
private UserDao userDao;
}
  为什么需要依赖呢?下⾯的代码中 UserDao 直接 new 写死了,如果此时新需求需要代理对象来处理业务就不⾏了,所以为了程序的灵活,需要改成上⾯的依赖代码,由程序控制对象的创建(IOC);
public class UserManagerImpl implements UserManagerServie{
java xml是什么
public void addUser(){
UserDao userDao = new UserDao();
}
}
  依赖注⼊(Dependency Injection)
  依赖注⼊是⼀个过程,对象通过构造⽅法参数、⼯⼚⽅法参数、构造或⼯⼚⽅法返回后在对象实例上设置的属性来定义它们的依赖项,从类外部注⼊依赖(容器在创建bean时注⼊这些依赖项),类不关⼼细节。这个过程从根本上说是bean⾃⾝的反向(因此得名控制反转),通过使⽤直接构造类或服务定位器模式来控制依赖项的实例化或位置。
依赖注⼊的基本原则是:应⽤组件不应该负责查资源或者其他依赖对象,配置对象的⼯作由IOC容器负责,即组件不做定位查询,只提供常规的Java⽅法让容器去决定依赖关系。
使⽤ DI 原则,代码会更清晰,并且当向对象提供它们的依赖时,解耦会更有效。对象不查其依赖项,也不知道依赖项的位置或类。因此,类变得更容易测试,特别是当依赖关系在接⼝或抽象类上时,它们允许在单元测试中使⽤ stub 或 mock 实现。
Spring中依赖注⼊有四种⽅式:构造⽅法注⼊(Constructor Injection),set注⼊(Setter Injection)、接⼝注⼊(Interface Injection)和字段注⼊(Field Injection),其中接⼝注⼊由于在灵活性和易⽤性⽐较差,现在从Spring4开始已被废弃。
(1) 构造⽅法注⼊(Constructor Injection):Spring Framework 更倾向并推荐使⽤构造⽅法注⼊
View Code
  xml配置⽂件对应bean的定义信息:
  也可以配置成下⾯的模式:
View Code
  1)构造函数参数解析:构造函数参数解析匹配通过使⽤参数类型实现。如果 bean definition 在构造函数参数中不存在潜在的歧义,那么构造函数参数的bean definition定义的顺序就是实例化bean时将这些参数提供给对应构造函数的顺序。
复制代码
package x.y;
public class ThingOne {
public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
// ...
}
}
复制代码
  假设 ThingTwo 和 ThingThree 类与继承⽆关,那么就不存在潜在的歧义。因此,以下配置可以很好
地⼯作,不需要在 标签中显式地指定构造函数参数索引或类型;
复制代码
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
复制代码   2)构造函数参数类型匹配
当引⽤另⼀个 bean 时,类型是已知的,可以进⾏匹配(就像前⾯的例⼦⼀样)。当使⽤简单类型时,例如true, Spring ⽆法确定值的类型,因此如果没有帮助,就⽆法按类型进⾏匹配。如下⾯的例⼦:
复制代码
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.ultimateAnswer = ultimateAnswer;
}
}
复制代码
  如果使⽤ type 属性显式地指定构造函数参数的类型,则容器可以使⽤简单类型的类型匹配。
  3)构造函数参数索引匹配:可以使⽤ index 属性显式地指定构造函数参数的索引,从0开始;   index 除了解决多个简单值的模糊性之外,还可以解决构造函数有两个相同类型的参数时的模糊性。
4)构造函数参数的名字匹配:除了上⾯的类型、索引匹配,还可以使⽤名字进⾏匹配;
  请记住,要使它开箱即⽤,代码编译时必须启⽤debug标志,以便 Spring 可以从构造函数中查参数名进⾏实例化创建。如果不能或不想使⽤ debug 标志编译代码,可以使⽤ JDK注解 @ConstructorProperties 显式地命名构造函数参数。
public class Point {
@ConstructorProperties({“x”, “y”})
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
private final int x, y;
}
复制代码
  关于 @ConstructorProperties 的作⽤:
⼀些序列化框架使⽤ @ConstructorProperties 将构造函数参数与相应的字段及其 getter 和 setter ⽅法关联起来,⽐如上⾯参数 x 和 y 对应的是 getX() 和 getY();
为此,它依赖于为字段命名 getter 和 setter ⽅法时使⽤相同的常见命名约定: getter 和 setter ⽅法名称通常是通过⼤写字段名称并在前缀加get或set创建的(或者对于布尔类型的 getter 是 is)。但是,使⽤单字母字段名的⽰例并不能很好地展⽰这⼀点。
⼀个最好的案例是:someValue 变成 getSomeValue 和 setSomeValue;
因此在构造函数属性的上下⽂中,@ConstructorProperties({“someValue”})表⽰第⼀个参数与 getter⽅法 getSomeValue和setter ⽅法 setSomeValue相关联;
请记住,⽅法参数名在运⾏时是不可见的。重要的是参数的顺序。构造函数参数的名称或构造函数实际设置的字段并不重要。下⾯仍然引⽤名为getSomeValue()的⽅法,然后对⽅法⾥⾯的值进⾏序列化:
复制代码
import com.fasterxml.jackson.databind.ObjectMapper;
import java.beans.ConstructorProperties;
import java.beans.XMLEncoder;
import java.io.ByteArrayOutputStream;
public class Point {
public Point(int a) {
this.x = a;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSomeValue() {
return y;
}
public static void main(String[] args) throws Exception {
//将bean信息进⾏xml格式输出:进⾏序列化
ByteArrayOutputStream stream = new ByteArrayOutputStream();
XMLEncoder encoder = new XMLEncoder(stream);
encoder.writeObject(new Point(1));
encoder.close();
System.out.println(stream);
}
}
结果
<?xml version="1.0" encoding="UTF-8"?> 10 复制代码   什么情况下使⽤@ConstructorProperties注解呢?
⼀般的POJO bean 都有set 和 get ⽅法,所以是可变的。在默认情况下,Jackson 将使⽤Java bean模式进⾏反序列化:⾸先通过使⽤默认(或零args)构造函数创建bean类的实例,然后使⽤⼀系列对setter的调⽤来设置每个属性值。但如果是⼀个不可变bean(没有set⽅法),⽐如上⾯的Point案例呢?现在没有了set⽅法,或者构造函数也是⽆参的,这时你就使⽤ @JsonProperty and @JsonCreator注解来进⾏序列号和反序列化了,如下⾯的案例:
View Code
     但这⾥存在⼀个问题,⽐如我在程序的多模块下使⽤了这个bean,在其中⼀个模块中我将它序列化成 JSON,但在另外⼀个模块中,我可能选择不同的序列号机制(⽐如YAML、XML),但由于Jackson不⽀持 YAML,我们将不得不使⽤不同的框架来序列号这些bean,⽽这些库可能需要它们⾃⼰的注解集,所以我们需要在这个 bean中添加⼤量的注解以⽀持对应的序列号框架,这样很不友好。这时就可以使⽤ @ConstructorProperties 注解来解决这个问题了,序列号框架⽐如 Jackson 框架从2.7版本就⽀持这个注解了;
View Code
    只要对应的序列化框架⽀持该注解,就可以使⽤更少的注解来被这些⽀持的框架进⾏序列化和反序列化了。
对于序列化,框架使⽤对象getter获取所有值,然后使⽤这些值序列化对象。当需要反序列化对象时,框架必须创建⼀个新实例。如果对象是不可变的,它没有任何可以⽤来设置其值的setter。构造函数是设置这些值的唯⼀⽅法。@ConstructorProperties注解⽤于告诉框架如何调⽤构造函数来正确地初始化对象。
Spring还可以使⽤@ConstructorProperties注解按名称查构造函数参数:
<bean id="point" class="testPackage.Point">
<constructor-arg name="xx" value="10"/>
<constructor-arg name="yy" value="20"/>
</bean>
复制代码
public class Point {
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("l");
Point point = (Point) Bean("point");
System.out.X());
System.out.Y());
}
5)当构造⽅法是私有时,可以提供⼀个静态⼯⼚⽅法供外部使⽤:
View Code
  静态⼯⼚⽅法的参数是由xml配置⽂件的标签提供的,与实际使⽤构造函数时完全相同。⼯⼚⽅法返回的类的类型不必与包含静态⼯⼚⽅法的类的类型相同(上⾯的案例中是相同的)。
(2) set注⼊(Setter Injection):由容器在调⽤⽆参数构造函数或⽆参数静态⼯⼚⽅法来实例化bean之后调⽤bean上的setter⽅法来完成的;
View Code
  xml配置⽂件对应bean的定义信息:
View Code
  (3) 接⼝注⼊(Interface Injection):
若根据 wikipedia 的定义,接⼝注⼊只是客户端向客户端依赖项的setter⽅法发布⼀个⾓⾊接⼝,它可以⽤来建⽴注⼊器在注⼊依赖时应该如何与客户端通信
View Code
Spring为 ResourceLoaders, ApplicationContexts, MessageSource和其他资源提供了开箱即⽤的资源插件接⼝:ResourceLoaderAware, ApplicationContextAware, MessageSourceAware等等,这⾥就使⽤到了接⼝注⼊;
我们以ApplicationContextAware接⼝为例,它的作⽤是Spring容器在创建bean时会扫描实现了这个接⼝的类,然后将这个容器注⼊给这个实现类,这样这个实现类就可以通过容器去获取bean等其他操作了。
复制代码
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
复制代码
那我们什么时候会需要⽤到 ApplicationContextAware这个接⼝呢?如果你需要查⼀些bean或访问⼀些应⽤程序⽂件资源,甚⾄发布⼀些应⽤程序范围的事件,这时你就需要⽤到这个接⼝了。
复制代码
@Component
public class MyClass implements ApplicationContextAware {