zoukankan      html  css  js  c++  java
  • Spring快速入门

    引言

    最近几天一直在忙着学习数据结构和算法,关于JavaEE的框架也有一阵子没更新了。那么今天就来聊一聊Spring框架吧,针对该框架写一篇快速入门的文章。

    Spring简介

    Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

    • 目的:解决企业应用开发的复杂性
    • 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
    • 范围:任何Java应用

    Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架。

    配置Bean

    首先来说一说在Spring框架中如何去配置Bean。
    通过一个简单案例感受一下:
    首先得导入Spring框架的jar包,然后创建一个类:

    package com.itcast.spring.bean;
    
    public class HelloWorld {
    
    	private String name;
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void hello() {
    		System.out.println("hello:" + name);
    	}
    }
    

    在传统的写法中,我们要想调用HelloWorld类的hello()方法,我们需要手动创建HelloWorld的实例,然后调用setName()方法给name赋值,接着调用hello()方法。但是有了Spring框架之后,对于对象的创建和属性的赋值都不需要我们操心,框架能够帮助我们完成。所以接下来创建Spring框架的配置文件applicationContext.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="helloWorld" class="com.itcast.spring.bean.HelloWorld">
    		<property name="name" value="Spring"></property>
    	</bean>
    	
    </beans>
    

    对于这段简单的配置,可以解释一下。bean是beans下的一个子节点,配置的是一个bean类的信息,然后是bean节点下的属性:

    • id:标识容器中的bean,id是唯一的
    • class:bean的全类名,因为框架是通过反射的方式在IOC容器中创建bean的实例,所以你需要提供类的全路径,这在很多框架中都能得到体现

    然后是property,该节点配置的是bean类中的属性信息,name即为属性名,但是需要注意的是,这个name值是根据setXXX()方法进行匹配的,如果没有setXXX()方法或者setXXX()方法和类中的属性名不一致,将会导致异常产生。而value就是属性的值。
    配置好后,我们编写测试代码:

    public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    		HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
    		helloWorld.hello();
    }
    

    首先通过ClassPathXmlApplicationContext去构造ApplicationContext 对象,传入配置文件名,接着通过getBean()方法得到HelloWorld实例,传入的是在配置文件中bean的id属性值。
    运行结果:

    hello:Spring
    

    需要注意的是,在bean类中你必须提供一个无参的构造方法,因为反射的实现需要无参构造。
    到这里,一个入门的Spring案例就完成了。

    Spring容器

    接下来,我们细细地研究一下。
    在SpringIOC容器读取bean配置创建bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器中获取bean实例并使用。
    在Spring中提供了两种类型的IOC容器实现:

    1. BeanFactory:IOC容器的基本实现
      BeanFactory是Spring框架的基础设施,面向Spring本身
    2. ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口
      ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory

    但无论使用何种方式,配置文件的写法都是一样的。
    ApplicationContext是BeanFactory的子接口,它有两个实现类:

    1. ClassPathXmlApplicationContext:从类路径下加载配置文件
    2. FileSystemXmlApplicationContext:从文件系统中加载配置文件

    所以获得ApplicationContext的实例可以有两种方式,刚才的案例中使用的就是第一种方式。

    获得了Spring容器后,我们是如何去获得bean实例的呢?
    通过getBean()方法:
    在这里插入图片描述
    可以看到,ApplicationContext提供了多个getBean()方法的重载,所以对于bean实例的获取,除了通过id属性值获取以外,还可以通过bean的类型获取:

    public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    		HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
    		helloWorld.hello();
    }
    

    这样也能获取到bean的实例,而且有一个好处就是不用强制类型转换了。

    属性值的注入

    在Spring框架中,有两种方式可以对bean类的属性进行赋值:

    1. 属性注入
      属性注入在开始的案例中已经使用到了,就是通过bean节点下的property节点进行注入,它通过setXXX()方法注入属性值,属性注入是实例应用开发中最常用的注入方式
    2. 构造方法注入
      构造方法注入顾名思义就是通过构造方法注入属性值,它通过bean节点下的constructor-arg节点进行注入

    对于构造方法注入属性值,有必要单独提取出来讲解一下,我们来看一个案例。
    创建一个bean类:

    package com.itcast.spring.bean;
    
    public class Car {
    
    	private String brand;
    	private String corp;
    	private double price;
    	private int maxSpeed;
    	
    	public Car(String brand, String corp, double price) {
    		super();
    		this.brand = brand;
    		this.corp = corp;
    		this.price = price;
    	}
    
    	@Override
    	public String toString() {
    		return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
    	}
    }
    

    然后配置一下:

    <?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的属性值 -->
    	<bean id="car" class="com.itcast.spring.bean.Car">
    		<constructor-arg value="Audi"></constructor-arg>
    		<constructor-arg value="ShangHai"></constructor-arg>
    		<constructor-arg value="250000"></constructor-arg>
    	</bean>
    </beans>
    

    接下来编写测试代码:

    public static void main(String[] args) {
    	ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    	Car car = (Car) ctx.getBean("car");
    	System.out.println(car);
    }
    

    运行结果:

    Car [brand=Audi, corp=ShangHai, price=250000.0, maxSpeed=0]
    

    因为是通过构造方法注入属性值,所以可以不需要setXXX()方法,从配置中可以知道,属性值是通过配置的顺序进行注入的,那么接下来我们修改一下Car类:

    package com.itcast.spring.bean;
    
    public class Car {
    
    	private String brand;
    	private String corp;
    	private double price;
    	private int maxSpeed;
    
    	public Car(String brand, String corp, double price) {
    		super();
    		this.brand = brand;
    		this.corp = corp;
    		this.price = price;
    	}
    
    	public Car(String brand, String corp, int maxSpeed) {
    		super();
    		this.brand = brand;
    		this.corp = corp;
    		this.maxSpeed = maxSpeed;
    	}
    
    	@Override
    	public String toString() {
    		return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
    	}
    }
    

    我们在Car类中新增了一个构造方法,然后我们重新配置一下bean:

    <?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="car2" class="com.itcast.spring.bean.Car">
    		<constructor-arg value="BMW"></constructor-arg>
    		<constructor-arg value="BeiJing"></constructor-arg>
    		<constructor-arg value="240"></constructor-arg>
    	</bean>
    </beans>
    

    我们想通过这三个属性值来得到一个Car的实例,接下来编写测试代码:

    public static void main(String[] args) {
    	ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    	Car car = (Car) ctx.getBean("car2");
    	System.out.println(car);
    }
    

    运行结果:

    Car [brand=BMW, corp=BeiJing, price=240.0, maxSpeed=0]
    

    问题就出现了,我明明是想通过第二个构造方法构造对象,传入的240是maxSpeed的值,但它仍然使用了第一个构造方法,所以仅仅靠参数顺序来注入是不合理的。
    不过不用担心,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"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    	<bean id="car2" class="com.itcast.spring.bean.Car">
    		<constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
    		<constructor-arg value="BeiJing"
    			type="java.lang.String"></constructor-arg>
    		<constructor-arg value="240" type="int"></constructor-arg>
    	</bean>
    </beans>
    

    其它地方不用修改,重新运行一下测试代码,结果如下:

    Car [brand=BMW, corp=BeiJing, price=0.0, maxSpeed=240]
    

    这样就达到了我们想要的结果。
    对于属性值的注入,还可以通过子节点下的value节点进行注入,效果是一样的。

    引用类型属性值的注入

    对字面值的注入有了一定的了解之后,我们单独看一下引用类型的属性值该如何注入:
    先创建一个bean类:

    package com.itcast.spring.bean;
    
    public class Person {
    
    	private String name;
    	private int age;
    	private Car car;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	public Car getCar() {
    		return car;
    	}
    
    	public void setCar(Car car) {
    		this.car = car;
    	}
    
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    	}
    }
    

    在配置文件中配置一下Person类:

    <?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="car2" class="com.itcast.spring.bean.Car">
    		<constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
    		<constructor-arg value="BeiJing"
    			type="java.lang.String"></constructor-arg>
    		<constructor-arg value="240" type="int"></constructor-arg>
    	</bean>
    	
    	<bean id="person" class="com.itcast.spring.bean.Person">
    		<property name="name" value="Tony"></property>
    		<property name="age" value="18"></property>
    		<property name="car" ref="car2"></property>
    	</bean>
    </beans>
    

    对于引用类型Car,我们可以通过property节点的ref属性指向对car的引用,因为上面我配置了一个id为car2的bean,所以这里直接通过id引用指向它。
    编写测试代码:

    public static void main(String[] args) {
    	ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    	Person person = (Person) ctx.getBean("person");
    	System.out.println(person);
    }
    

    运行效果:

    Person [name=Tony, age=18, car=Car [brand=BMW, corp=BeiJing, price=0.0, maxSpeed=240]]
    

    和上面类似,也可以使用子节点ref进行配置。

    <bean id="person" class="com.itcast.spring.bean.Person">
    		<property name="name" value="Tony"></property>
    		<property name="age" value="18"></property>
    		<property name="car">
    			<ref bean="car2"/>
    		</property>
    </bean>
    

    我们还可以在属性或构造器里包含一个bean的声明,这样的bean称为内部bean,无法被外部访问。

    <bean id="person" class="com.itcast.spring.bean.Person">
    		<property name="name" value="Tony"></property>
    		<property name="age" value="18"></property>
    		<property name="car">
    			<bean class="com.itcast.spring.bean.Car">
    				<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
    				<constructor-arg value="ShangHai" type="java.lang.String"></constructor-arg>
    				<constructor-arg value="250000" type="double"></constructor-arg>
    			</bean>
    		</property>
    </bean>
    

    Spring和Struts、Hibernate框架一样,也支持级联属性。所以我们还可以通过级联属性赋值。

    <property name="car.price" value="150000"></property>
    

    可以通过这样的方式给Car类的属性赋值。

    集合属性值注入

    在引用类型中,又有一个特殊的群体,集合。包括Set、List、Map。
    修改Person类代码:

    package com.itcast.spring.bean;
    
    import java.util.List;
    
    public class Person {
    
    	private String name;
    	private int age;
    	private List<Car> cars;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + ", cars=" + cars + "]";
    	}
    
    	public List<Car> getCars() {
    		return cars;
    	}
    
    	public void setCars(List<Car> cars) {
    		this.cars = cars;
    	}
    }
    

    其中有一个集合类型Car,该如何在配置文件中进行配置呢?

    <?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的属性值 -->
    	<bean id="car" class="com.itcast.spring.bean.Car">
    		<constructor-arg value="Audi"></constructor-arg>
    		<constructor-arg value="ShangHai"></constructor-arg>
    		<constructor-arg value="250000"></constructor-arg>
    	</bean>
    
    	<bean id="car2" class="com.itcast.spring.bean.Car">
    		<constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
    		<constructor-arg value="BeiJing" type="java.lang.String"></constructor-arg>
    		<constructor-arg value="240" type="int"></constructor-arg>
    	</bean>
    	
    	<!-- 如何配置集合属性 -->
    	<bean id="person2" class="com.itcast.spring.bean.Person">
    		<property name="name" value="Jack"></property>
    		<property name="age" value="20"></property>
    		<property name="cars" >
    			<list>
    				<ref bean="car"/>
    				<ref bean="car2"/>
    			</list>
    		</property>
    	</bean>
    </beans>
    

    编写测试代码:

    public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Person person = (Person) ctx.getBean("person2");
    		System.out.println(person);
    }
    

    运行结果:

    Person [name=Jack, age=20, cars=[Car [brand=Audi, corp=ShangHai, price=250000.0, maxSpeed=0], Car [brand=BMW, corp=BeiJing, price=150000.0, maxSpeed=240]]]
    

    对于Set和Map集合,Spring提供了set标签和map标签进行配置,配置原理相同,不作重复介绍。Map集合会有点特殊,因为它是以键值对的方式存储的,所以它是通过Map节点下的子节点entry进行配置的,entry节点包含key和value-ref属性,也简单配置一下给大家看看吧。

    <map>
    	<entry key="aa" value-ref="car"></entry>
    	<entry key="bb" value-ref="car2"></entry>
    </map>
    

    属性文件值注入

    还有一种特殊类型,Properties,就是我们熟知的配置文件,在Spring中,同样可以通过配置直接将值注入到该属性中,看一个案例你们就会明白。
    创建一个bane类:

    package com.itcast.spring.bean;
    
    import java.util.Properties;
    
    public class DataSource {
    
    	private Properties properties;
    
    	public Properties getProperties() {
    		return properties;
    	}
    
    	public void setProperties(Properties properties) {
    		this.properties = properties;
    	}
    
    	@Override
    	public String toString() {
    		return "DataSource [properties=" + properties + "]";
    	}
    }
    

    然后对该类进行配置:

    <?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="dataSource" class="com.itcast.spring.bean.collection.DataSource">
    		<property name="properties">
    			<props>
    				<prop key="user">root</prop>
    				<prop key="password">123456</prop>
    				<prop key="url">jdbc:mysql:///test</prop>
    				<prop key="driver">com.mysql.jdbc.Driver</prop>
    			</props>
    		</property>
    	</bean>
    </beans>
    

    配置完成后,编写测试代码:

    public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    		DataSource dataSource = (DataSource) ctx.getBean("dataSource");
    		System.out.println(dataSource);
    }
    

    运行结果:

    DataSource [properties={user=root, url=jdbc:mysql:///test, password=123456, driver=com.mysql.jdbc.Driver}]
    

    实现过程非常简单,这样就将对数据库的配置注入到Properties属性中,关于对数据库的操作就可以通过这样进行封装。

    鉴于是对Spring的快速入门,所以也没有去深入地介绍Spring的一些内容,关于Spring的快速入门,就说到这里,接下来还会出几篇Spring高级或者Spring一些其它的知识点。

  • 相关阅读:
    链表基础操作2
    数据结构第二章课后作业
    CSAPP第二個實驗bomblab
    链表的基础操作1
    Codeforces 375
    Codeforces 372
    Codeforces 367
    线性同余方程组
    【除草】反演
    【转】组合数求模
  • 原文地址:https://www.cnblogs.com/blizzawang/p/11411528.html
Copyright © 2011-2022 走看看