Spring简单介绍——以及IOC容器和Bean配置

Spring简单介绍

——以及IOC容器和Bean的配置

Spring简介

Spring是一个开源的框架,也是一个IOCAOP容器框架。

Sprin特点

①非侵入式:基于Spring开发的应用中的对象可以不依赖与Spring的API。

②依赖注入:DI—Dependency Injection,反转控制(IOC)最经典的实现。

③面向切面编程:Aspect Oriented Programming——AOP。

④容器:Spring是一个容器,因为它包含并且管理应用对象的声明周期。

⑤组件化:Spring实现了使用简单组件配置组合成一个复杂的应用,在Spring中可以使用XML和Java注解组合这些对象。

⑥一站式:在IOC和AOP的基础上可以整合各种企业应用开源框架和优秀的第三方类库。

Spring模块

在这里插入图片描述

搭建Spring运行时环境

  1. 加入JAR包(五个jar必须先导入)

① Spring自身JAR包:spring-framework-4.0.0.RELEASE\libs目录下

  • spring-beans-4.0.0.RELEASE.jar
  • spring-context-4.0.0.RELE2ASE.jar
  • spring-core-4.0.0.RELEASE.jar
  • spring-expression-4.0.0.RELEASE.jar

② commons-logging-1.1.1.jar

  1. 在Spring Tool Suite工具中通过如下步骤创建Spring的配置文件

​ ① File->New->Spring Bean Configuration File

​ ② 为文件取名字 例如:applicationContext.xml

IOC容器

IOC(Inversion of Control):反转控制,IOC容器在最底层实质上就是一个对象工厂。

反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效率。这种行为也称为查找的被动形式。

DI(Dependency Injection):依赖注入

IOC 就是一种反转控制的思想, 而DI是对IOC的一种具体实现。

IOC容器在Spring中的实现

1)在通过IOC容器读取Bean的’实例之前,需要先将IOC容器本身实例化。

2)Spring提供了IOC容器的两种实现方式

① BeanFactory:IOC容器的基本实现,是Spring内部的基础设施,是面向Spring本身的,不是提供给开发人员使用的。

ApplicationContext:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory。

ApplicationContext的主要实现类

  1. ClassPathXmlApplicationContext:对应类路径下的XML格式的配置文件

  2. FileSystemXmlApplicationContext:对应文件系统中的XML格式的配置文件

  3. 在初始化时就创建单例的bean,也可以通过配置的方式指定创建的Bean是多实例的。

bean的属性赋值

(1)依赖注入的方式

A.通过bean的setXxx()方法赋值(最常用)

创建一个Employee类

package bean;

public class Employee {
	private Integer id;
	private String name;
	private String desc;
	public Employee(Integer id, String name, String desc) {
		super();
		this.id = id;
		this.name = name;
		this.desc = desc;
	}
	public Employee() {
		super();
		System.out.println("无参构造器被调用了");
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		System.out.println("setId");
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		System.out.println("setName");
		this.name = name;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		System.out.println("setDesc");
		this.desc = desc;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", desc=" + desc + "]";
	}
	
}

创建配置文件XML

<bean id="employee01" class="bean.Employee">
    <!--name="xxx"中的xxx不是随便设置的,就是将bean.Employee中setXxx()方法名都变为小写,比如xxx,value的值是自己设置的,类似于构造器初始化设置的值。-->
		<property name="id" value="1001" ></property> 
		<property name="name" value="张三" ></property>
		<property name="desc" value="好人1" ></property>
</bean>

创建测试类

package test;

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

import bean.Employee;

public class Test01 {
	public static void main(String[] args) {
    /*创建Spring容器对象,在创建容器对象的时候,会读取spring的配置文件,从配置文件中,可以知道, 当前容器管理了那些对象的创建,同时会将容器所管理的对象给创建出来。*/
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        // 从Spring容器对象中获取员工
		Employee employee = context.getBean("employee01", Employee.class);
		System.out.println(employee);
}

执行结果:

无参构造器被调用了
setId
setName
setDesc
Employee [id=1001, name=张三, desc=好人1]
B.通过bean的构造器赋值(了解)
1) 按照构造函数中的参数名字进行匹配

Employee类中其他都不变,有参构造变为如下:

public Employee(Integer id, String name, String desc) {
		super();
		System.out.println("有参构造被调用了");
		this.id = id;
		this.name = name;
		this.desc = desc;
	}

配置文件XML改为如下:

<bean id="employee02" class="bean.Employee">
		<constructor-arg name="id" value="1002"></constructor-arg>
		<constructor-arg name="name" value="李四"></constructor-arg>
		<constructor-arg name="desc" value="好人2"></constructor-arg>
</bean>

执行结果:

有参构造被调用了//此时不调用set()方法
Employee [id=1002, name=李四, desc=好人2]
2) 通过索引值指定参数位置

Employee类不变,只是改变一下配置文件:

<bean id="employee03" class="bean.Employee">
		<constructor-arg index="0" value="1003"></constructor-arg>
		<constructor-arg index="1" value="王五"></constructor-arg>
		<constructor-arg index="2" value="好人3"></constructor-arg>
</bean>

执行结果:

有参构造被调用了
Employee [id=1003, name=王五, desc=好人3]
3) Spring自动匹配合适的构造器

自动匹配合适的构造器,要求传递的参数类型必须和构造函数形参类型一致!

Employee类不变,只是改变一下配置文件:

<bean id="employee04" class="bean.Employee">
		<constructor-arg  value="1004"></constructor-arg>
		<constructor-arg  value="钱六"></constructor-arg>
		<constructor-arg  value="好人4"></constructor-arg>
</bean>

执行结果:

有参构造被调用了
Employee [id=1004, name=钱六, desc=好人4]
4) 通过类型区分重载的构造器

在Employee类中添加Double类型的salary属性,其他属性不改变,并提供get/set方法,和toString方法,提供新的构造函数,这个构造函数不需要desc。

package bean;

public class Employee {
	private Integer id;
	private String name;
	private String desc;
	private Double salary;
	
	public Employee(Integer id, String name, String desc) {
		super();
		this.id = id;
		this.name = name;
		this.desc = desc;
	}
	
	public Employee(Integer id, String name, Double salary) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	
	public Employee() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
	public Double getSalary() {
		return salary;
	}
	public void setSalary(Double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", desc=" + desc + ", salary=" + salary + "]";
	}
}

改变一下配置文件:

<bean id="employee05" class="bean.Employee">
		<constructor-arg value="1005"></constructor-arg>
		<constructor-arg value="冯7"></constructor-arg>
		<constructor-arg value="10000"></constructor-arg>
</bean>

执行结果

Employee [id=1005, name=7, desc=10000, salary=null]//当有两个构造器时,前面应该调用接收String类型的构造函数,也调用接收Double类型参数的构造器,原因是反射底层在获取类中所有构造方法的时候,放到了一个数组中,如果数组中的第一个可以匹配,那么后面的就不在匹配了。

遍历构造器:

public static void main(String[] args){
	testConstructor();
}
public static void testConstructor() {
		Class cla = Employee.class;
		Constructor[] cons = cla.getDeclaredConstructors();
		for (Constructor constructor : cons) {
			System.out.println(constructor);
		}
}

结果如下:

public bean.Employee(java.lang.Integer,java.lang.String,java.lang.String)
public bean.Employee(java.lang.Integer,java.lang.String,java.lang.Double)
public bean.Employee()

问题的解决:在xml文件中设置type

<bean id="employee05" class="bean.Employee">
		<constructor-arg value="1005"></constructor-arg>
		<constructor-arg value="冯7"></constructor-arg>
		<constructor-arg value="10000" type="java.lang.Double"></constructor-arg>
</bean>

结果如下:

Employee [id=1006, name=冯七,salary=10000.0]

字面值

  1. 可以使用字符串表示的值,可以通过value属性或value子节点的方式指定。

  2. 基本数据类型及其封装类、String等类型都可以采取字面值注入的方式

  3. 若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起来

创建一个Book类

package bean;

public class Book {
	private String isbn;
	private String name;
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Book [isbn=" + isbn + ", name=" + name + "]";
	}
}

在spring_ioc.xml文件中进行配置

<bean id="book01" class="bean.Book">
    <!--通过value属性赋值-->
	<property name="isbn" value="j001"></property>
	<property name="name" value="活着"></property>
</bean>
-------------------------------------------------------------------------------------
<bean id="book02" class="bean.Book">
    <!--通过value标签赋值-->
	<property name="isbn">
		<value>j001</value>
	</property>
	<property name="name">
		<value>活着</value>
	</property>
</bean>
-------------------------------------------------------------
<bean id="book03" class="bean.Book">
    <!--通过value标签赋值,可以省略标签体,直接以“/”结束-->
	<property name="isbn" value="j001"/>
	<property name="name" value="活着"/>
</bean>

<!--如果有特殊的字符可以使用实体转义,也可以放在<![CDATA[]]中,<![CDATA[]]不能使用value属性,只能使用value标签-->
<property name="name">
	<value>
    	<![CDATA[!@#!编程思想]]>
    </value>
</property>

引用其他的bean

创建员工类Employee和部门类Department

package bean;

public class Employee {
	private Integer id;
	private String name;
	private String desc;
	private Double salary;
	private Department dept;
	
	
	public Employee(Integer id, String name, String desc, Double salary, Department dept) {
		super();
		this.id = id;
		this.name = name;
		this.desc = desc;
		this.salary = salary;
		this.dept = dept;
	}
	
	public Employee() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}



	public void setName(String name) {
		this.name = name;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public Double getSalary() {
		return salary;
	}
    
	public void setSalary(Double salary) {
		this.salary = salary;
	}

	public Department getDept() {
		return dept;
	}

	public void setDept(Department dept) {
		this.dept = dept;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", desc=" + desc + ", salary=" + salary + ", dept=" + dept
				+ "]";
	}

}
package bean;

public class Department {
	private Integer id;
	private String name;
	public Department() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Department(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Department [id=" + id + ", name=" + name + "]";
	}

}

在12.xml文件中配置部门属性

<bean id="employee01" class="bean.Employee">
 	<property name="id" value="1006"></property>
 	<property name="name" value="张三丰"></property>
 	<property name="desc" value="员工"></property>
 	<property name="salary" value="1500"></property>
 	<property name="dept" ref="dept"></property>
 </bean>
<bean id="dept" class="bean.Department">
	<property name="id" value="200"></property>
	<property name="name" value="武当山"></property>
	</bean>

</beans>

测试类

package test;

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

import bean.Employee;

public class Test03 {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("12.xml");
		Employee employee01 = context.getBean("employee01", Employee.class);
		System.out.println(employee01);
	}
}

结果:

Employee [id=1006, name=张三丰, desc=员工, salary=1500.0, dept=Department [id=200, name=武当山]]

给bean的级联属性赋值

<bean id="employee02" class="bean.Employee">
	<property name="id" value="1007"></property>
 	<property name="name" value="张丰"></property>
 	<property name="desc" value="员工02"></property>
 	<property name="salary" value="15002"></property>
 	<property name="dept" ref="dept"></property>
 	
 	<!--级联属性操作-->
	<property name="dept.name" value="峨眉派"></property>
 </bean>

	
<bean id="dept" class="bean.Department">
	<property name="id" value="200"></property>
	<property name="name" value="武当山"></property>
</bean>

结果:

Employee [id=1007, name=张丰, desc=员工02, salary=15002.0, dept=Department [id=200, name=峨眉派]]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值