Spring的初体验-1

一. 概述
  1. 官网 https://spring.io/
  2. 核心jar包
commons-collections-3.2.jar
commons-logging.jar
spring-aop-4.0.6.RELEASE.jar
spring-beans-4.0.6.RELEASE.jar
spring-context-4.0.6.RELEASE.jar
spring-core-4.0.6.RELEASE.jar
spring-expression-4.0.6.RELEASE.jar
  1. 默认以单例形式管理bean
  • src/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.xsd">
        
	<bean id="helloWorld" class="com.bee.HelloWorld"></bean>
	
</beans>

被管理的类

public class HelloWorld {

	public void say(){
		System.out.println("Spring4俺来也");
	}
}

测试类

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

import com.bee.HelloWorld;

public class Test {

	public static void main(String[] args) {
		ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
		//强转的方式
		//HelloWorld helloWorld=(HelloWorld)ac.getBean("helloWorld");
		
		//非强转的方式
		HelloWorld helloWorld=ac.getBean("helloWorld", HelloWorld.class);
		helloWorld.say();
	}
}

这样就可以让Spring来管理bean。

二. Spring IoC

IoC(控制反转:Inverse of Control),用于解除类之间的耦合,他是Spring架构的核心。IoC体现的是设计模式中的“好莱坞法则:don’t call us, we’ll call you”。

这里的“控制”就是new对象。在哪个类中new对象,那个类就控制被new的对象。控制反转就是要取消类中的new,把所有获得对象的new都统一收归到Spring框架里来,比如:

ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");

这样就只有一个new,用于生成Spring框架的对象。Spring框架就可以统一管理各个对象,而不是让用户的类来管理对象。用户对类对象的控制权就反转过来交给Spring框架——控制反转。

现在设定一个场景用于解释控制反转:

项目主管Boss安排测试人员Mufasa和Daoba对代码进行测试。用户类是Boss,而类Mufasa和Daoba受Boss管理,Boss类依赖Mufasa和Daoba对象。

  1. 用户类直接控制依赖的对象
public class Mufasa {
	public void doTest() {
		System.out.println("我不入地狱谁入地狱,一个字——干。");
	}
}

public class Daoba {
	public void doTest() {
		System.out.println("王侯将相宁有种乎,老子就不干,咋地。");
	}
}

//Boss类与Mufasa和Daoba对象深度耦合——如果Boss不想要Daoba,还得修改自身的代码再编译。
public class Boss {
	public void comeOnBaby() {
		Mufasa mufasa = new Mufasa();
		mufasa.doTest();
		Daoba daoba = new Daoba();
		daoba.doTest();
	}
}

//测试
public class ClientGo {

	public static void main(String[] args) {
		Boss boss = new Boss();
		boss.comeOnBaby();
	}
}

由于用户类直接控制了依赖的对象,所以用户类与依赖对象之间就形成了强耦合——改变依赖关系需要修改源代码。

  1. 使用控制反转
public interface Tester {
	void doTest();
}

public class Mufasa implements Tester {
	@Override
	public void doTest() {
		System.out.println("我不入地狱谁入地狱,一个字——干。");
	}
}

public class Daoba implements Tester {
	@Override
	public void doTest() {
		System.out.println("王侯将相宁有种乎,老子就不干,咋地。");
	}
}

public class Boss {
	private Tester tester;
	//这里就是Boss的依赖注入(DI)
	public void setTester(Tester tester) {
		this.tester = tester;
	}

	public void comeOnBaby() {
		tester.doTest();
	}
}

//测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.bee.beans.Boss;

public class ClientGo {

	public static void main(String[] args) {
		ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");
		Boss boss = (Boss) appContext.getBean("boss");
		boss.comeOnBaby();
	}
}

控制反转的实现需要借助依赖注入(DI,Dependency Injection)特性。当通过Spring IoC将对象创建出来以后,必然需要对新建对象的属性(对象引用)进行赋值——这个赋值的操作在Spring这里就叫依赖注入。

  1. 把控制权交给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="mufasa" class="com.bee.beans.Mufasa"></bean>
    
    <bean id="daoba" class="com.bee.beans.Daoba"></bean>
    
    <bean id="boss" class="com.bee.beans.Boss">
        <property name="tester" ref="mufasa"></property>
    </bean>
  
</beans>

对依赖对象的管理变成Spring框架配置文件中一个bean标签的管理。在配置文件中还可以通过property标签来管理依赖注入——这里Boss方便地完成了对Mufasa的依赖,而剔除了对Daoba的依赖——不用修改自身源代码。

这一切的实现基础是反射。值得关注的是控制反转后看不到用户类的new操作了。

三. Spring DI的常见方式

先定义一个实体bean

public class People {
	private int id;
	private String name;
	private int age;
	
	public People() {
		super();
	}
	public People(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	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 "People [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
}
  1. 属性注入
<?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="people" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="穆法沙"></property>
		<property name="age" value="8"></property>
	</bean>
</beans>
  1. 构造函数注入(通过类型;通过索引;两者兼用)
通过类型
<bean id="people" class="com.bee.entity.People">
	<constructor-arg type="int" value="2"></constructor-arg>
	<constructor-arg type="String" value="辛巴"></constructor-arg>
	<constructor-arg type="int" value="6"></constructor-arg>
</bean>

通过索引
<bean id="people" class="com.bee.entity.People">
	<constructor-arg index="0" value="2"></constructor-arg>
	<constructor-arg index="1" value="辛巴"></constructor-arg>
	<constructor-arg index="2" value="6"></constructor-arg>
</bean>

两者兼用
<bean id="people" class="com.bee.entity.People">
	<constructor-arg index="0" type="int" value="2"></constructor-arg>
	<constructor-arg index="1" type="String" value="辛巴"></constructor-arg>
	<constructor-arg index="2" type="int" value="6"></constructor-arg>
</bean>
  1. 工厂方法注入(非静态工厂;静态工厂)
  • 非静态工厂
public class PeopleFactory {
	public People createPeople(){
		People p=new People();
		p.setId(3);
		p.setName("刀疤");
		p.setAge(10);
		return p;
	}
}

配置文件beans.xml

<bean id="peopleFactory" class="com.bee.factory.PeopleFactory"></bean>
<bean id="people" factory-bean="peopleFactory" factory-method="createPeople"></bean>
  • 静态工厂
public class PeopleFactory {
	public static People createPeople(){
		return new People(4, "波波", 8);
	}
}

配置文件beans.xml(静态方法是跟着类class走的)

<bean id="peopleFactory" class="com.bee.factory.PeopleFactory"></bean>
<bean id="people" class="com.bee.factory.PeopleFactory" factory-method="createPeople"></bean>
四. Spring注入参数

实体bean

public class People {
	private int id;
	private String name;
	private int age;
	private Dog dog;
	private List<String> hobbies=new ArrayList<String>();
	private Set<String> loves=new HashSet<String>();
	private Map<String,String> works=new HashMap<String,String>();
	private Properties addresses=new Properties();
	
	public People() {
	}
	public People(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
	public Set<String> getLoves() {
		return loves;
	}
	public void setLoves(Set<String> loves) {
		this.loves = loves;
	}
	public List<String> getHobbies() {
		return hobbies;
	}
	public void setHobbies(List<String> hobbies) {
		this.hobbies = hobbies;
	}
	public Map<String, String> getWorks() {
		return works;
	}
	public void setWorks(Map<String, String> works) {
		this.works = works;
	}
	public Properties getAddresses() {
		return addresses;
	}
	public void setAddresses(Properties addresses) {
		this.addresses = addresses;
	}
	public Dog getDog() {
		return dog;
	}
	public void setDog(Dog dog) {
		this.dog = dog;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	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 "People [id=" + id + ", name=" + name + ", age=" + age
				+ ", dog=" + dog + ", hobbies=" + hobbies + ", loves=" + loves
				+ ", works=" + works + ", addresses=" + addresses + "]";
	}
}

public class Dog {
	private String name;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

参数注入的例子

<?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">

	1. 基本类型值
	<bean id="people1" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
	</bean>
	
	<bean id="dog1" class="com.bee.entity.Dog">
		<property name="name" value="Jack"></property>
	</bean>
	
	2. 注入bean
	<bean id="people2" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<property name="dog" ref="dog1"></property>
	</bean>
	
	3. 内部bean
	<bean id="people3" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<property name="dog">
			<bean class="com.bee.entity.Dog">
				<property name="name" value="Tom"></property>
			</bean>
		</property>
	</bean>
	
	4. null值
	<bean id="people4" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<property name="dog">
			<null></null>
		</property>
	</bean>
	
	5. 级联属性
	<bean id="people5" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<property name="dog.name" value="Jack2"></property>
	</bean>
	
	6. 集合类型属性
	<bean id="people6" class="com.bee.entity.People">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
		<property name="age" value="11"></property>
		<property name="dog" ref="dog1"></property>
		<property name="hobbies">
			<list>
				<value>唱歌</value>
				<value>跳舞</value>
			</list>
		</property>
		<property name="loves">
			<set>
				<value>唱歌2</value>
				<value>跳舞2</value>
			</set>
		</property>
		<property name="works">
			<map>
				<entry>
					<key><value>上午</value></key>
					<value>写代码</value>
				</entry>
				<entry>
					<key><value>下午</value></key>
					<value>测试代码</value>
				</entry>
			</map>
		</property>
		<property name="addresses">
			<props>
				<prop key="address1">aaaaa</prop>
				<prop key="address2">bbbbb</prop>
			</props>
		</property>
	</bean>
	
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值