Java框架——Spring(一)

Spring

Spring是2003年兴起的一个轻量级的Java开发框架,为了解决企业开发的复杂度(耦合度)而创建的
spring就是管理对象创建的一个容器
Spring的核心是控制反转(IOC)和面向切面编程(AOP)
Spring主要作用是为代码解耦

根据功能不同,一个系统中的代码分为主业务逻辑和系统级业务逻辑
主业务逻辑:有专业的应用的场景,复用性低,
系统级业务逻辑:相对功能独立,主要为主业务提供系统级服务,如,日志,安全,事务等
对于主业务逻辑的耦合使用控制反转(IOC)
对于主业务逻辑和系统级业务逻辑之间的耦合使用面向切面编程(AOP)

什么是Spring?
实质:1.Spring是个容器;
作用:2.用于降低代码间的耦合度;
核心:3.根据不同的代码它采用了IoC(控制反转)和AOP(面向切面编程)两种核心技术

Spring的下载

Spring的下载:https://repo.spring.io/list/libs-release-local/org/springframework/spring/5.0.9.RELEASE/
修改版本号下载不同版本的spring	

要使用Spring的核心,还要下载spring-framework-RELEASE-dependencies.zip(spring的支持库)资源包
下载地址https://repo.spring.io/webapp/#/search/quick/eyJzZWFyY2giOiJxdWljayIsInF1ZXJ5Ijoic3ByaW5nLXNlY3VyaXR5In0=
英文版在线APIhttps://docs.spring.io/spring/docs/5.0.9.RELEASE/javadoc-api/

第一个Spring程序

Spring本质是管理对象的容器
不使用Spring时对象的创建需要手动使用new来创建
Person p = new Person("张三",23);
p.getname();
使用Spring来完成对象的创建与调用
流程:
a)创建Spring容器
b)从Spring容器中获取自定义对象
c)调用自定义对象的方法

1.准备jar包
首先是核心容器的4个jar包,在spring-libs文件下
spring-beans-5.0.9.RELEASE.jar
spring-context-5.0.9.RELEASE.jar
spring-core-5.0.9.RELEASE.jar
spring-expression-5.0.9.RELEASE.jar

Spring-dependencies资源包下的org.apache.log4j文件下的log4j功能测试包
com.springsource.org.apache.log4j-1.2.15.jar

org.apache.commons文件下com.springsource.org.apache.commons.logging文件夹下的jar包提供了日志的功能
com.springsource.org.apache.commons.logging-1.1.1.jar

2.在类路径(src)下写配置文件,通常文件名为applicationContext.xml

3.xml中添加约束
eclipse添加约束文件——window——Preferemces——XML 	Catalog ——Add 添加约束文件
<?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="myObject" class="spring.Person"></bean>
	<!--id值任意,class值为类的全类名-->
</beans>
4.建立一个普通类,使用@Test注解完成对spring的测试
@Test
public void test02() {
	//1.获取容器对象,需要applicationContext.xml的文件路径作为参数
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	//2.从容器对象中获取自定义对象,参数是bean标签的id值
	Person bean = (Person) ac.getBean("myObject");
	//3.调用指定方法
	bean.getName();
	ac.close();
	//ApplicationContext没有close方法,但是ClassPathXmlApplicationContext有close方法
}

ApplicationContext 接口

ApplicationContext 接口有两个实现类
ClassPathXmlApplicationContext(最常用):从类路径(src文件夹)下查找配置文件,使用较多(在JavaWeb项目)
FileSystemXmlApplicationContext:从根路径(或本地盘符)下查找配置文件

查看底层源码
ApplicationContext 接口继承了ListableBeanFactory接口, HierarchicalBeanFactory接口
任选一个查看源码
HierarchicalBeanFactory继承了BeanFactory接口
BeanFactory接口中有getBean()方法来获取对象
BeanFactory接口有一个XmlBeanFactory的实现类

XmlBeanFactory实现类的构造需要Resource类型的参数
Resource是一个接口,需要的是它的实现类ClassPathResource
ClassPathResource的构造器需要一个String类型的路径参数,String path

获取Spring容器的第二种方法:
//获取容器对象
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml") );
//从容器对象中获取对象
Person bean = (Person) ac.getBean("myObject");	
bean.getName();
结果与之前是一致的
但是XmlBeanFactory在3.1以后已经被废弃,不再推荐使用


在不改变处理逻辑的基础上,可以改为

Resource resource=new ClassPathResource("applicationContext.xml");  
BeanFactory factory=new DefaultListableBeanFactory();  
BeanDefinitionReader bdr=new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory1);  
bdr.loadBeanDefinitions(resource); 
//loadBeanDefinitions方法源码跟踪https://www.cnblogs.com/feng-jq/p/10282196.html
BeanFactory是spring的原始接口,其实现类的功能较为单一,特点是在获取对象时才会创建对象
ApplicationContext功能较多,在spring容器启动时就会去创建所有对象

ApplicationContext容器的唯一性

ApplicationContext是管理对象的容器
如何保证ApplicationContext对象只有一个呢?
servlet中servletContext就是单例的,随着服务启动而创建,随着项目关闭而销毁
解决:用监听器监听servletContext的启动,在监听器中添加ApplicationContext的创建
	获取时从servletContext中获取
1.监听器需要导入spring-web相关jar包
2.在web.xml中注册监听器ContextLoaderListener
3.在web.xml中配置spring容器加载信息
ContextLoaderListener 实现了ServletContextListener接口
ContextLoaderListener 继承了ContextLoader类中有一个属性
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
指定<context-param><param-name>为contextConfigLocation
<!--注册监听器 在服务器启动时创建Application容器  -->
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置监听器的同时需要配置Application文件的路径的参数-->
<context-param>
	<param-name>contextConfigLocation </param-name>
	<param-value>classpath:applicationContext.xml </param-value>
</context-param>
<param-name>的值是固定的——contextConfigLocation
<param-value>的值是classpath:xml文件的路径

ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息

4.获取ApplicationContext 对象
//1.获取servletContext 对象
//servletContext sc = ....
//2.获取容器对象
WebApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc);
//3.从容器中获取对象
Service s =(Service)ac.getBean("service");

spring配置文件

bean元素标签:需要spring容器管理的对象
	name属性:被管理对象的别名,根据这个别名来获取对象,作用与id属性一致
			可以重复,后一个bean会被返回,因为后一个<bean>将前一个<bean>覆盖
			可以使用特殊字符,但不能带空格
			可以有多个name值<bean name="b1,b2,b3">
			如果id和name都没有指定,则用类全名作为name
			getBean("com.Person")返回该实例
	scope属性:指定当前bean的范围,"singleton"默认值当前bean是单例的
	class属性:被管理对象的完整类名,
	id属性:必须以字母开头,不可以重复,不可以包含数字,下划线,连字符,句号,冒号等特殊字符,可以包含/
	init-method:当前Bean对象创建后调用该初始化方法
	destroy-method:当前Bean对象销毁前调用该方法

通过scope属性指定的5种作用域;
1.prototype  每次通过getBean获取的都是不同的实例
2.singleton  使用singleton定义的Bean类都是单例的,默认是singleton  
3.request 对于每一次HTTP请求都将产生一个不同的Bean实例
4.session 对于每一个不同的HTTP session都将产生不同的实例
5.global session 
注意:
1.对于scope值为request ,session和global session 时 ,只有在Web应用中使用Spring时,该作用域才有用
2.对于scope值为prototype的原型模式,该Bean的实例是在代码中使用时才会进行装配
3.对于scope值为singleton  的单例模式,该Bean是在容器被创建时即被装配好


一个applicationContext.xml不能写入太多的bean配置
可以分批写入不同的applicationContext.xml中
在总文件applicationContext.xml中引入这些配置文件即可
<import resource="com/dao/applicationContext2.xml"/>
<import resource="com/service/applicationContext3.xml"/>

Bean的作用域

Bean标签的scope可以指定五种作用域
默认是单例的
所谓单例是指通过同一个bean的id获取的对象是单例的
<bean id="myPerson" class="spring.Person"  >
Person bean = (Person) ac.getBean("myPerson");
Person bean2 = (Person) ac.getBean("myPerson");
System.out.println(bean == bean2);//true

<bean id="myPerson" class="spring.Person"  >
<bean id="myPerson2" class="spring.Person"  >	
Person bean = (Person) ac.getBean("myPerson");
Person bean2 = (Person) ac.getBean("myPerson2");
System.out.println(bean == bean2);//false
这种方法的bean的注册一般是将scope设为prototype来获取不同的实例对象  

获取对象的方式

1.无参构造器
<bean id="/myObject" class="spring.SomeServiceimpl"></bean>
本质是调用类的无参构造器来创建对象
	//获取容器
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	//获取对象	
	Person bean = (Person) ac.getBean("/myObject");
2.静态工厂(了解即可)
<bean id="/myObject" class="spring.ServiceFactorty" factory-method="getSomeService"></bean>
使用自定义类中的静态方法来完成需要的对象
将这个自定义的工厂类注册到Spring容器即可
public class ServiceFactorty {
	public static SomeService getSomeService() {
		return new SomeServiceimpl();
	}
}
	//获取容器
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	//获取对象	
	Person bean = (Person) ac.getBean("/myObject");
3.实例工厂
<bean id="factorty" class="spring.ServiceFactorty" ></bean> 配置工厂对象
<bean id="user"  factory-bean="factorty" factory-method="getSomeService"></bean>
使用自定义工厂类的普通方法来返回需要的对象
再在容器中注册工厂类
然后获取工厂类的对象调用其方法获得需要的对象
public class ServiceFactorty {
	public SomeService getSomeService() {
		return new SomeServiceimpl();
	}
}
	//获取容器
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	//获取对象	
	Person bean = (Person) ac.getBean("user");

定制Bean的生命始末

在applicationContext.xml中bean标签有两个属性init-method,destroy-method
init-method:其值是初始化的方法名,无参构造器和set设值注入方法执行后会执行这个方法
destroy-method:其值是Bean销毁之前调用的方法名,在这个对象销毁前调用
1.自定义Person类,定义两个方法,life()输出初始化,death()输出Bean销毁前	
2.xml中配置bean的生命始末
<bean id="per" class="com.Person " init-method="life"
	destroy-method="death"></bean>
public class Person {
	public SomeServiceimpl() {
		super();
		System.out.println("Person的无参构造");
	}
	@Override
	public String doSome() {
		//获取当前类所在的包名
		System.out.println(this.getClass().getPackage().getName() + ":" + "Person ...");
		return "abcdfgg";
	}
	public void life() {
		System.out.println("Bean生命开始");
	}
	public void death() {
		System.out.println("Bean生命结束之前");
	}

}
销毁方法的执行有2个条件:
a.当前的Bean是singleton的
b.要手动关闭容器
ApplicationContext没有close方法,实现类ClassPathXmlApplicationContext有close方法
	@Test
	public void test01() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		//2.获取注册的对象
		Person bean = (Person) ac.getBean("per");
		//3.调用对象方法
		String doSome = bean.doSome();
		System.out.println(doSome);
		//4.手动关闭容器
		((ClassPathXmlApplicationContext) ac).close();
	}
Bean的执行顺序:
	Person的无参构造
	Bean生命开始	
	com.Person:Person ...
	abcdfgg
	Bean生命结束之前

Bean后处理器

Bean后处理器是一种特殊的Bean,容器中所有Bean在初始化时
(在无参构造执行之后,在init-method方法执行之前与之后各执行一个Before和After方法),
均会自动调用该类的两个方法
该类自动调用,无需id属性;
有2个方法(postProcessBeforeInitialization,postProcessAfterInitialization)分别在所有Bean初始化之前,之后调用
1.自定义Bean后处理器,需要实现BeanPostProcessor接口,重写上述的2个方法
public class MyBeans implements BeanPostProcessor {
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("Bean后处理器的Before方法");
		return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);

	};

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("Bean后处理器的After方法");
		System.out.println("beanName: " + beanName);
		//beanName就是bean标签的name值,没有name就是id值
		return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);

	};

}

2.自定义Person类,写上init与death方法并在xml中配置信息
public class Person {
	private int age;
	private String name;

	public Person() {
		super();
		System.out.println("Person无参构造");
	}
	public void init() {
		System.out.println("init方法");
	}
	//...
<!-- 注册Bean后处理器 -->
<bean class="spring_01.MyBeans" />
<!-- 注册Person和初始化方法 -->
<bean id="myPerson" class="spring_01.Person" init-method="init">
		<property name="age" value="23"></property>
		<property name="name" value="张三"></property>
</bean>

测试

	@Test
	public void test() {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person bean = (Person) ac.getBean("myPerson");	
		System.out.println(bean);
	}
	/*Person无参构造
	Bean后处理器的Before方法
	init方法
	Bean后处理器的After方法
	beanName: myPerson
	Person [age=23, name=张三]*/

Bean后处理器的使用

对对象的功能进行增强
案例一:将字符串全转为大写
	@Override		//匿名内部类调用外部的成员变量,需要这个变量是final修饰的
	public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
		System.out.println("执行After方法。。。。。。。。。");
		Object ob = Proxy.newProxyInstance(
				bean.getClass().getClassLoader(),//指定动态代理类的类加载器, 
				bean.getClass().getInterfaces(),//指定动态代理类需要实现的所有接口, 
/*最后一个参数是必须实现了InvactionHandler接口的对象,通过newProxyInstance函数返回proxy的实例是调用实现了
InvactionHandler接口对象重写的invoke方法,而此方法中里面的参数对象是被代理类的实现了某个接口的具体方法,
通俗一点就是中介的角色,具体干实事是被代理类实现某接口的具体方法,
当然在invoke方法中可以加入一些业务逻辑代码,也是就是spring框架里面的aop通知实现的原理*/
				new InvocationHandler() {
					@Override
					public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
					//arg0表示对象,arg1表示对象的方法,arg2表示方法的参数
						Object invoke = arg1.invoke(bean, arg2);
						return ((String)invoke).toUpperCase();//功能增强为将返回的字符串结果改为大写
					}
				}
				);
		return ob;
	}
案例二:只对某一个类进行增强
所有Bean初始化后都会调用Bean后处理器的方法
	@Override		
	public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
		System.out.println("执行After方法。。。。。。。。。");
		if("myServlce1 ".equals(beanName)){
		//beanName是Bean元素标签的id或name属性值
			Object ob = Proxy.newProxyInstance(
					bean.getClass().getClassLoader(), 
					bean.getClass().getInterfaces(), 
					new InvocationHandler() {						
						@Override
						public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
							Object invoke = arg1.invoke(bean, arg2);
							return ((String)invoke).toUpperCase();
						}
					}
					);
			return ob;
		}
		return bean;
	}
案例三:只对某一个类的某一个方法进行增强
		Object ob = Proxy.newProxyInstance(
			bean.getClass().getClassLoader(), 
			bean.getClass().getInterfaces(), 
			new InvocationHandler() {
				
			@Override
			public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
				Object invoke = arg1.invoke(bean, arg2);
				if("doSome".equals(arg1.getName())){
					return ((String)invoke).toUpperCase();
				}
				return invoke ;
				}
			}
		);
		return ob;

Bean从创建到销毁的时间点

一个自定义的Person从创建到调用自身的toString方法再到销毁经过了多少个时间点?
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person bean = (Person) ac.getBean("myPerson");		
		System.out.println(bean);	//调用自身toString方法
		((ClassPathXmlApplicationContext)ac).close();
		/*
		1-Person无参构造
		2-Person-set方法
		3-setBeanName:获取配置自身Bean的name值
		4-setBeanFactory:获取配置自身Bean的工厂
		5-Bean后处理器的Before方法
		6-InitializingBean接口的初始化方法
		7-Bean标签定义的init方法
		8-Bean后处理器的After方法
		9-真正的业务方法Person [age=23, name=张三]
		10-DisposableBean接口的destroy方法
		11-Bean标签定义的death方法
		*/
		
1.BeanNameAware接口,只有一个setBeanName方法获取自身Bean的名字
2.BeanFactoryAware接口,只有一个setBeanFactory方法获取自身所在的工厂对象
3.InitializingBean接口,只有一个afterPropertiesSet方法,在初始化之前调用该方法
4.DisposableBean接口,只有一个destroy方法,在对象销毁前调用
public class Person implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean
	public Person() {
		super();
		System.out.println("1-Person无参构造");
	}
	
	public void setAge(int age) {
		this.age = age;
		System.out.println("2-Person-set方法");
	}
	
	@Override
	public void setBeanName(String name) {
		System.out.println("3-setBeanName:获取配置自身Bean的name值");
	}
	
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("4-setBeanFactory:获取配置自身Bean的工厂");
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("6-InitializingBean接口的初始化方法");
	}
	
	public void init() {
		System.out.println("7-Bean标签定义的init方法");
	}
		
	@Override
	public String toString() {
		return "9-真正的业务方法Person [age=" + age + ", name=" + name + "]";
	}
	
	@Override
	public void destroy() throws Exception {
		System.out.println("10-DisposableBean接口的destroy方法");
	}

	public void death() {
		System.out.println("11-Bean标签定义的death方法");
	}
public class MyBeans implements BeanPostProcessor {
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("5-Bean后处理器的Before方法");
		return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);

	};

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("8-Bean后处理器的After方法");	
		return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);

	};

}
<bean id="myPerson" class="spring.Person" init-method="init" destroy-method="death">
	<property name="age" value="23"></property>
	<property name="name" value="张三"></property>
</bean>
<!-- 注册Bean后处理器 -->
<bean class="spring_01.MyBeans" />

IOC(控制反转)

IoC的实现方式:
一,依赖查找(DL),容器提供回调接口和上下文环境的组件,程序代码需要提供具体的查找方式,比如要创建被调用者的对象,需要提供查询地址
二,依赖注入(DI),程序不做定位查找,由容器自行完成,缺点是不分区,所以被调用对象不能重名
依赖注入(DI)是目前最优秀的解耦方式,依赖注入让spring的Bean之间以配置文件的方式组织在一起,而不是以硬编码的形式耦合在一起

IOC是一种思想,一种概念,它的实现方式有很多,
最常用是依赖查找和依赖注入,而spring使用是依赖注入;
依赖注入是目前最优秀的解耦方式

实现IOC需要DI做支持

DI(依赖注入)

定义一个Student类
	属性:name,age,school
	提供set方法和toString 方法
定义School类
	属性name
	提供set方法和toString 方法
一,设值注入(常用)
必须要有set方法才能完成注入
<bean id="mySchool" class="com.spring.School">
		<property name="name" value="武汉大学"></property>
</bean>
<bean id="myStudent" class="com.Student">
	<property name="name" value="张三"></property>
	<property name="age" value="23"></property>
	<property name="school" ref="mySchool"></property>
	<!--对于域属性的注入需要ref,其他属性是value-->
 </bean>
//测试
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu = (Student) ac.getBean("myStudent");
System.out.println(stu.toString());
二,构造注入		
可以不需要set方法,必须要带参构造器,没有无参也能执行,但最好带上无参构造器
<bean id="mySchool" class="com.spring.School">
		<property name="name" value="武汉大学"></property>
</bean>
<bean id="myStudent" class="com.Student">
		<constructor-arg  index="0" value="张三"></property>  <!--index属性表示构造方法参数的索引,从0开始-->
		<constructor-arg  index="1" value="23"></property>
		<constructor-arg  index="2" ref="mySchool"></property><!--index属性用的不多-->
		
		<constructor-arg  name="name" value="张三"></property>  <!--一般都是使用name属性-->
		<constructor-arg  name="age" value="23"></property>
		<constructor-arg  name="school" ref="mySchool"></property>
		<constructor-arg  name="参数名" index="参数下标" value="参数值" type="参数类型"></property> <!--四个属性一起用可以定位到任意一个参数-->
</bean>
三,p命名空间注入(了解即可)	
p命名空间注入——走的还是set方法
需要添加新的约束
xmlns:p="http://www.springframework.org/schema/p"
<!--配置文件-->
<bean id="mySchool" class="com.spring.School"  p:name="北京大学" />
<bean id="myStudent" class="com.Student" p:name="王五" p:age="25" p:school-ref="mySchool"/>
四,c命名空间注入(了解即可)	
添加约束
xmlns:c="http://www.springframework.org/schema/c"
<!--配置文件-->
<bean id="mySchool" class="com.spring.School"  c:name="北京大学" />
<bean id="myStudent" class="com.Student" c:name="王五" c:age="25" c:school-ref="mySchool"/>
五,SPEL注入
SPEL:spring表达式语言
<bean id="myStudent" class="com.Student">
		<property name="name" value="#{myStudent1.name}"></property> 
		<!--获取bean标签元素id值对应的bean对象的name属性赋值给当前的name属性
		要求myStudent1对应的类中有get方法
	-->
		<property name="school" ref="mySchool"></property>
		<!--引用类型的值直接写bean引用对象的name值或者id值即可-->
</bean>

特殊类型的注入(常用)

 为array,list,set,map,properties,对象集合等注入参数

1.对于String数组的参数注入
<bean id="myStudent" class="com.bjpowernode.spring_01.Student"> 
	<property name="name"> <!--对于String数组的参数注入-->
		<array>
			<value>张三</value>
			<value>李四</value>
			<ref bean="mySchool"/> <!--对象属性注入-->
		</array>
	</property>
</bean>		
		
2.对于List集合的参数注入
<property name="list"> <!--对于List集合的参数注入-->
		<list>
			<value>及格</value>
			<value>优秀</value>
			<ref bean="mySchool"/> <!--对象属性注入-->
		</list>
</property>
3.对于对象数组的参数注入
<property name="school"><!--对于对象属性的数组参数注入-->
		<array>
			<ref bean="mySchool1"/><!--除了引用类型以外一般都是value标签-->
			<ref bean="mySchool2"/>
		</array>
</property>
4.对于Set集合的参数注入
<property name="set">
	<set>
		<value>3</value>
		<value>2</value>
	</set>
</property>
5.对于Map集合的参数注入
<property name="map">
	<map>
		<entry key="mobile" value="123456"/>
		<entry key="qq" value="654321"/>
	</map>
</property>
6.对于properties的参数注入
<property name="per">
	<map>
		<prop key="addr" >123456</prop >
		<prop key="phone" >654321</prop >
	</map>
</property>
7.对于set集合和list集合的快速注入,不适合map类型
<property name="set" value="张wu,李四"/>
<property name="list" value="及格,优秀"/>

域属性的自动注入

根据bean的Name值来完成域属性的自动注入
1.拥有域属性的类在bean标签中需要设置
<bean ... autowire="byName"> 到容器中自动查找与类的域属性同名的Bean的id
2.域属性类型的bean的id为域属性的属性名
<bean id="school" class="com.spring.School" />
//Student类:
    private String name;
	private int age;
	private School school;
	//<bean id="school" >
	//<bean ... autowire="byName"> 
<bean id="school" class="com.spring.School" >
		<property name="name" value="清华大学"/>
	</bean>
<bean id="myStudent" class="com.spring.Student" autowire="byName"> 
	<property name="name" value="张三"/>
	<property name="age" value="23"/>
</bean>
根据bean的类型来完成域属性的自动注入
1.<bean ...  autowire="byType"> 
2.自动到容器查找与实体类同类型(包括子类)的Bean
并自动将该Bean对象自动注入给该域属性,此时id可省略
有多个相同类型的Bean会报错

同类抽象Bean(了解)

<bean id="myStudent1" class="com.spring.Student">
		<property name="name" value="张三" />
		<property name="age" value="23" />
		<property name="address"  value="武汉"/>
		<property name="sex"  value=""/>	
</bean>
<bean id="myStudent2" class="com.spring.Student">
		<property name="name" value="李四" />
		<property name="age" value="24" />
		<property name="address"  value="武汉"/>
		<property name="sex"  value=""/>		
</bean>
以上两个Bean是同一个类型且部分信息重合,可以使用同类抽象Bean完成注册
<bean id="myStudent" class="com.spring.Student"  abstract="true"><!--定义为抽象类-->
		<property name="address"  value="武汉"/>
		<property name="sex"  value=""/>		
</bean>
<bean id="myStudent2" parent="myStudent" >
		<property name="name" value="张三" />
		<property name="age" value="23" />
</bean>

异类抽象Bean(了解)

<bean id="myStudent" class="com.spring.Student">
		<property name="name" value="狗蛋" />
		<property name="age" value="13" />
		<property name="address"  value="武汉"/>
		<property name="sex"  value="1"/>	
</bean>
<bean id="myDog" class="com.spring.Dog">
		<property name="name" value="狗蛋" />
		<property name="age" value="4" />
		<property name="address"  value="武汉"/>
		<property name="sex"  value="1"/>		
</bean>
以上两个Bean不是同一个类型且部分信息重合,可以使用异类抽象Bean完成注册
<bean id="myDate"   abstract="true"><!--定义为抽象类,告诉Spring,这个不用创建对象-->
		<property name="name" value="狗蛋" />
		<property name="address"  value="武汉"/>
		<property name="sex"  value="1"/>
</bean>
<bean id="myStudent" class="com.spring.Student"  parent="myDate">		
		<property name="age" value="23" />	
</bean>
<bean id="myDog" class="com.spring.Dog" parent="myDate">
		<property name="age" value="4" />	
</bean>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值