Spring简介:
Spring是一个为简化企业应用级开发的简单框架。
它是轻量级的:Spring是非入侵的,基于Spring开发的对象可以不依赖于Spring的API。
Spring之HelloWorld
com.hust.HelloWorld
public class HelloWorld {
private String name;
public HelloWorld() {
System.out.println("constrcutor...");
}
public void setNameNow(String name2) {
System.out.println("setting");
this.name = name2;
}
public void sayHello(){
System.out.println("hello ,"+this.name);
}
}
com.hust.Main
Spring提供了两种IOC容器的实现
-BeanFactory:IOC容器的基本实现。面向Spring本身
-Applicationcontext:是BeanFactory的子接口,提供了更高级的特性。面向开发者。
几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory.
public class Main {
public static void main(String[] args) {
//创建IOC容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContent.xml");
//从IOC容器中获取bean实例
HelloWorld hello =(HelloWorld) ac.getBean("helloWorld");
hello.sayHello();
}
}
Spring支持三种依赖注入的方式:
属性注入;
即通过setter方法注入Bean属性值或依赖对象。
构造器注入;
借助构造器注入初始化bean;借助< constructor-arg>元素
静态工厂方法注入;(很少使用,不推荐)
applicationContent.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.hust.HelloWorld" >
<property name="nameNow" value="Spring"></property>
</bean>
</beans>
IOC和DI
IOC(Inversion of Control):其思想是反转资源获取的方向。传统的资源查找要求组件向容器发起资源查找;作为回应,容器适时返回资源,应用了IOC之后,则是容器主动将资源推送给它所管理的组件,组件所要做的仅是选择一种适合的方式来接受资源。
DI(Dependency Injection)IOC 的另一种表述方式,即组件以一些预定义好的方式(例如setter方法)接受来自容器资源的注入。
没有IOC之前,我们是怎么办的呢?
1. 原始社会(很早很早以前):
2. 工厂设计模式
3. IOC控制反转:
注入属性值的细节
Spring中可以使用< list> < set> < map>来配置集合属性;
这些标签可以通过value指明常量值,ref指明bean引用,< /null>指定空元素,或者内嵌其它集合;
< map> 标签中可以用多个< entry>作为子标签,每个标签包含一个键和值;
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringModelInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
">
<!--
配置bean
class: bean的全类名,通过反射的方式在IOC中创建bean,所以一定要有无参数构造函数
id:标识容器的bean,唯一性
-->
<!--属性注入使用property元素,为name指定bean的属性名称(具体以set方法后的字符为准)
value是指定的属性值-->
<bean id="helloWorld" class="com.hust.HelloWorld" >
<property name="nameNow" value="Spring"></property>
</bean>
<!--通过构造方法配置bean属性 -->
<bean id="car" class="com.hust.Car">
<constructor-arg value="baoma" type="java.lang.String"></constructor-arg>
<constructor-arg value="beijing" index="1"></constructor-arg>
<constructor-arg value="1200000" type="double"></constructor-arg>
</bean>
<!--指定参数的位置和类型,区分重载的构造器 -->
<bean id="car2" class="com.hust.Car">
<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
<!--如果字面值含有特殊字符,可以使用<![CDATA[] ]> 包起来-->
<constructor-arg index="1"><value><![CDATA[Guangdong^]]></value></constructor-arg>
<constructor-arg value="250" type="int"></constructor-arg>
</bean>
<bean id="person" class="com.hust.Person">
<property name="name" value="Tom"></property>
<property name="age" value="21"></property>
<!--可以使用property 的ref属性建立bean之间的引用关系 -->
<property name="car" ref="car"></property>
<!--为级联属性赋值 -->
</bean>
<bean id="person2" class="com.hust.Person" p:age="23" p:name="Lisa">
<!--内部bean ,不能被外部引用-->
<property name="car" >
<bean class="com.hust.Car">
<constructor-arg name="brand" value="DAzhong"></constructor-arg>
<constructor-arg name="corp" value="Zhejiang"></constructor-arg>
<constructor-arg name="price" value="140000"></constructor-arg>
</bean>
</property>
</bean>
<bean id="person3" class="com.hust.Person">
<constructor-arg value="David"></constructor-arg>
<constructor-arg value="21"></constructor-arg>
<constructor-arg ref="car2"></constructor-arg>
<!--为级联属性赋值 -->
<property name="car.price" value="230000"></property>
</bean>
<util:list id="cars">
<ref bean="car"></ref>
<ref bean="car2"></ref>
</util:list>
<bean id="person4" class="com.spring.Collection.Person">
<property name="name" value="Xiong"></property>
<property name="age" value="29"></property>
<property name="car" ref="cars">
<!--若想把list独立出来, 可以使用util命名空间(现在是在内部的) -->
</property>
</bean>
<bean id="person5" class="com.spring.Collection.NewPerson">
<property name="name" value="Rose"></property>
<property name="age" value="23"></property>
<property name="cars" >
<map>
<entry key="A" value-ref="car2"></entry>
<entry key="B-" value-ref="car"></entry>
</map>
</property>
</bean>
</beans>
xml中的自动装配
可以在xml中实现自动装配,需要做的仅是在< bean>的autowire属性中指定自动装配的模式;
byType: 根据类型(bean 里面的class属性)自动装配;若在xml中含有多个满足条件的bean,则会抛出异常
byName: 根据名称自动装配,必须将目标bean的id设置成属性名(set方法后面的第一个首字母变小写);
autowire.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="addressteo" class="com.spring.Autowired.Address" p:city="Hangzhou" p:street="guanshan"></bean>
<bean id="carteo" class="com.spring.Autowired.Car" p:brand="Fute" p:price="321412"></bean>
<bean id="car" class="com.spring.Autowired.Car" p:brand="Luhu" p:price="1380000"></bean>
<bean id="xiangda" class="com.spring.Autowired.Person"
p:name="Kitty" autowire="byName"></bean>
</beans>
Person类:
package com.spring.Autowired;
/**
* Created by kaixin on 2018/8/21.
*/
public class Person {
private String name;
private Address address;
private Car car;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address=" + address +
", car=" + car +
'}';
}
public void setName(String name) {
this.name = name;
}
public void setAddressteo(Address address) {
this.address = address;
}
public void setCarteo(Car car) {
this.car = car;
}
}
bean之间的关系:继承,依赖
(这里的继承指的是配置的继承,不是指那个extends)
被继承的bean我们叫它父bean,继承父bean的配置的bean我们叫它子bean。子bean可以覆盖父bean中的属性;父bean可以用abstract声明为抽象的bean,即不能被IOC容器实例化生成对象,只能被parent属性继承(作为模板)。
通过depend-on属性设置bean前置依赖的bean,这里只是保证了car先于person实例化,后于person销毁,person并没有把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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.spring.Autowired.Address"
p:street="yuyuanlu" p:city="wuhan" abstract="true"></bean>
<!--bean配置的继承,用parent属性指定继承哪个bean的配置-->
<bean id="address2" parent="address" p:street="luoyulu"></bean>
<bean id="car2" class="com.spring.Autowired.Car" p:brand="falali" p:price="20000000"></bean>
<!--要求配置这个person时,必须有一个关联的car,即这个person依赖于car -->
<bean id="person" class="com.spring.Autowired.Person"
p:name="Wangsichong" p:addressteo-ref="address2" depends-on="car2" ></bean>
</beans>
Person{name='Wangsichong', address=Address{city='wuhan', street='luoyulu'}, car=null}
Spring容器中Bean的作用域
作用域一般指:这个对象的可见范围或可用域;
这里的作用域可以认为是bean定义与bean实例对象的关系。
通过scope属性来配置bean的作用域。
singleton:单例模式(默认值),在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
SpEL
Spring表达式语言:使用#{ … }作为界定符
作用:
- 通过id对bean进行引用
- 调用方法以及引用bean对象的属性
- 计算表达式、动态赋值
spel.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.spring.spel.Address"
p:street="sandianxilu" p:city="nanchang" ></bean>
<bean id="car" class="com.spring.spel.Car" p:brand="tesila" p:price="230000">
<!--调用静态方法或静态属性,在spel中用T() ,它返回一个Class.Object,再调用静态方法或属性-->
<property name="typrperimeter" value="#{T(java.lang.Math).PI *80}"></property>
</bean>
<bean id="person" class="com.spring.spel.Person" p:name="casual" >
<!--用spel引用其它的bean -->
<property name="carteo" value="#{car}"></property>
<!--用spel应用其它bean的属性 -->
<property name="city" value="#{address.city}"></property>
<!-- 使用spel运算符 来动态赋值-->
<property name="info" value="#{car.price>=300000 ? 'super_VIP':'VIP' }"></property>
</bean>
</beans>
Person类
public class Person {
private String name;
private Car car;
private String city;
//汽车的价格大于300000的话,info为super_VIP
//否则为VIP
private String info;
public String getName() {
return name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public void setName(String name) {
this.name = name;
}
public void setCarteo(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", car=" + car +
", city='" + city + '\'' +
", info='" + info + '\'' +
'}';
}
public Car getCar() {
return car;
}
}