IOC&DI
IOC(Inversion of Control),其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源,作为回应呢,容器适时的返回资源,而应用了IOC之后,则是容器主动的将资源推送给它所管理的组件,组件所要做的仅仅是选择一种合适的方式来接受资源,这种行为也被称为查找的被动形式。
DI(Dependency Injection),IOC的另一种表达方式:即组件以一些预先定义好的方式,例如:setter方法,接受来自如容器的资源注入。
配置Bean
|
|
|
|
Bean配置方式 |
通过全类名(反射)、通过工厂方法(静态工厂方法&实例工厂方法)、FactoryBean |
|
IOC容器 |
BeanFactory、ApplicationContext |
|
依赖注入方式 |
属性注入、构造器注入 |
|
注入属性值细节 |
|
|
自动转配 |
|
|
Bean之间的关系 |
继承、依赖 |
|
Bean的作用域 |
singleton、prototype、web环境作用域 |
|
使用外部属性文件 |
|
|
spEL |
|
|
IOC容器中Bean的生命周期 |
|
|
Spring4.x新特性 |
泛型依赖注入 |
配置Bean-知识点1:Bean整体配置思路
整体配置思路就2个:基于XML文件的方式、基于注解的方式

id标识容器中的Bean,id必须是唯一的。
class是类的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器。

配置Bean-知识点2:Spring容器
在Spring IOC容器读取Bean配置并创建Bean实例之前,必须对它进行实例化,只有在容器实例化之后,才可以从IOC容器里获取Bean实例并使用。
Spring提供了2种类型的IOC容器:
①BeanFactory:IOC容器的基本实现;
②ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口;
总结:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,因此大多数场景都直接使用ApplicationContext,而不是底层的BeanFactory,无论哪种方式,其配置文件都是一样的。

配置Bean-知识点3:ApplicationContext

ApplicationContext的主要的实现类:
①ClassPathXmlApplicationContext:从类路径下加载配置文件;
②FileSystemXmlApplicationContext:从文件系统中加载配置文件;
注意事项:
①ConfigurableApplicationContext扩展了Application-
Context,新增2个方法:refresh()和close()方法,从而让ApplicationContext具有启动、刷新、关闭上下文的能力。
②ApplicationContext在初始化上下文时,就实例化所有单例的Bean。
③WebApplicationContext是专门为Web应用而准备的,允许从相对于web根目录的路径中完成初始化工作。
配置Bean-知识点4:依赖注入方式
3种依赖注入方式:属性注入、构造器注入、工厂方法注入(不推荐)。
①属性注入本质是通过setter方法注入Bean的属性值/依赖的对象。属性注入使用<property/>元素,使用name属性来指定Bean的属性名,value属性/<value/>子节点指定属性值。
这种属性注入是应用最广泛的注入方式。
当我把setName注释掉之后,系统报错,也从侧面证明其是用过setter方法来设置属性值的:

注意:


系统也能正常执行,这说明:Spring先获取name属性值,然后在属性值的基础上再添加set前缀,例如:name=”name22”,其实在Bean中并没有name22这个属性,但还是能执行成功,说明Spring关心的是setXXXX中的XXXX,而不是Bean中具体的某个属性名。
②构造方法注入是通过构造方法注入Bean的属性值/依赖对象,保证了Bean实例在实例化后就可以使用。构造器注入在<constructor-arg/>元素里声明属性name、index、type来说明参数值。






配置Bean-知识点5:字面值
在知识点4中学习了依赖注入方式,但是,在设置value属性时,则还有另外的知识点。
字面值:可用字符串表示的值,可以通过<value/>子标签或value属性进行注入,其中基本数据类型及其封装类、String等类型都可以采取字面值注入的方式,但是,如果字面值中包含特殊字符,则必须使用<![CDATA[字面值]]>把字面值包裹起来。

配置Bean-知识点6:引用其它Bean
要使Bean能够互相访问,就必须在Bean配置文件中指定对Bean的引用。在Bean的配置文件中,可以通过<ref/>标签或者ref属性来为Bean的属性或构造器参数指定对某个Bean的引用。
这种在属性或者构造器里包含的Bean的声明,这样的Bean称为内部Bean。内部Bean,不管有没有id属性,都无法被外部引用,只能被内部使用。


配置Bean-知识点7:null值和级联属性
针对null值,可以使用专用的<null/>标签为Bean的字符串或其他对象类型的属性来注入null值。

Spring也支持级联属性

这里在使用级联属性时,必须首先初始化属性car,然后才能为级联属性car.weight赋值,否则会出现异常。
配置Bean-知识点8:集合属性
Spring可以通过一组内置的XML标签,例如<list/>、<set/>、<map/>来配置集合属性。
初始化java.util.List类型的属性,需要使用<list/>标签,在标签内包含一些元素,而这些元素可以通过<value/>指定简单的常量值,也可以通过<ref/>指定对其他Bean的引用,也可以通过<bean/>指定内置Bean定义,也可以通过<null/>指定空元素,甚至可以内嵌其他集合。
初始化数组类型的属性跟List一样,都使用<list/>。
初始化java.util.Set类型的属性,需要使用<set/>标签,定义元素的方法与<list/>一样。
初始化java.util.Map类型的属性,需要使用<map/>标签定义,<map/>标签内部包含多个<entry/>子标签,每一个<entry/>子标签只能包含一个键盘和一个值;在<key/>标签里定义键,因为键和值的类型没有限制,因此可以自由地为键和值使用<value/>、<ref/>、<bean/>、<null/>元素,当然,也可以将Map的键和值作为<entry/>的属性来定义:简单常量使用key和value来定义,Bean引用通过key-ref和value-ref属性来定义。
初始化java.util.Properties类型的属性,可以使用<props/>标签来定义,该标签内部包含多个<prop>作为子标签,每个<prop>标签必须定义key属性。

配置Bean-知识点9:使用utility scheme定义集合
使用基本的集合标签来定义集合时,不能将集合作为独立的Bean定义,进而导致其他Bean无法引用该集合,所以无法在不同Bean之间共享集合,为了解决这个问题,可以使用util schema里的集合标签定义独立的集合Bean,需要注意的是,必须在<beans>根元素里添加util schema定义。
说白了就是通过util schema来把集合独立出来,作为一个共享资源来被其他Bean使用。




配置Bean-知识点10:使用p命名空间
为了简化XML文件的配置,越来越多的XML文件采用属性,而不是子元素来配置信息。因此,从Spring2.5开始引入了一个新的命名空间p,来通过<bean>元素属性的方式配置Bean的属性,因此,在使用p命名空间之后,基于XML的配置方式将进一步简化。



通过截图,我们可以返现,P命名空间可以大幅度减少开发人员代码量。
配置Bean-知识点11:自动装配
XML配置里的Bean自动装配,指的是Spring IOC容器可以自动装配Bean,这里的自动装配你可以理解为把XXX-ref=YYYY这种显示配置给删掉,然后IOC容器自己来完成这块工作,而我们需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式,autowire取值范围如下:
①byType根据类型自动装配:若IOC容器中有多个与目标Bean类型一致的Bean,这种情况下,Spring将无法判定哪个Bean最适合该属性,所以不能执行自动装配;
核心在于,假如当前Bean中定义了一个XXXX类型的变量,那么,自动装配的时候,就去查找class=”XXXX”的<bean/>,如果能找到且只有1个,则自动装配,如果没找到/IOC容器有2个及以上的类型匹配的Bean,则抛出异常。
②byName根据名称自动装配:必须将目标Bean的名称,与属性名设置的完全相同;
核心在于,假如当前Bean中定义了一个setXXXX的方法,那么,自动装配的时候,就去查找id=”XXXX”的<bean/>,如果能找到且只有1个,则自动装配,如果没找到/IOC容器有2个及以上的id匹配的Bean,则抛出异常。
③constructor通过构造器自动装配:当Bean中存在多个构造器时,这种自动装配方式将会很复杂,因此不推荐使用。
自动装配的缺点在于:
①在Bean配置文件里设置autowire属性进行自动装配将会装配Bean的所有属性,然而,如果只希望装配个别几个属性时,autowire则不够灵活。
②autowire属性,要么根据类型自动装配,要么根据名称自动装配,只能二选一,不能同时选择。
③实际开发中,自动装配用的很少,因为明确清晰的配置会减少不必要问题,进而减少为了解决这些问题而花费的时间、精力等。



配置Bean-知识点12:bean之间的关系
Bean之间的关系就2种:继承、依赖。
①继承:这里的继承,指的是Spring配置上的继承,而不是JAVA语法上的继承。Spring允许继承<bean/>的配置,被继承的<bean/>称为父<bean/>,继承这个父<bean/>的<bean/>称为子<bean/>。
子<bean/>从父<bean/>中继承配置,包括<bean/>的属性配置,当然,子<bean/>也可以覆盖从父<bean/>继承过来的配置,需要注意的是,并不是父<bean/>里所有属性都会被继承,比如autowire、abstract就不会被继承;子<bean/>也可以忽略父<bean/>的class属性,让子<bean/>指定自己的类,而共享相同的属性配置,但前提是父<bean/>的abstract=true。
父<bean/>可以作为配置模板,也可以作为<bean/>实例,如果只想把父<bean/>作为模板,则可以设置<bean/>的abstract属性为true,这样Spring将不会实例化该<bean/>。
注意:当某个<bean/>的abstract=true时,可以不填写class属性。



②依赖:Spring允许用户通过depends-on属性来设定Bean前置依赖的Bean,前置依赖的Bean会在当前Bean实例化之前提前创建好。如果前置依赖于多个Bean,则可以通过逗号或者空格方式来配置Bean的名称。



注意:我在People中定义了变量food,但我在XML中并没有为food设置p:food-ref,所以在println中food=null,因此这里的“依赖”指的是实例的创建,而不是实例的创建 + 注入。
注入动作是额外的,需要通过p或者<property/>来注入。
配置Bean-知识点13:bean的作用域
Spring IOC容器中,针对<bean/>默认都是单例的,即工程中通过id来获取的JAVA实例都是同一个实例。
为了适应不同场景下对实例的要求,这里涉及到bean的作用域scope问题,在<bean/>中有scope属性,该属性取值范围如下:
①prototype原型:容器初始化时不创建Bean的实例,而是在每次请求时都创建一个新的Bean实例,并返回。即什么时候用,就什么时候新建一个bean实例并返回给调用者,每次调用,每次新new一个实例,每次都不通。
②request:request只用于web程序,通常是和XmlWeb-
ApplicationContext共同使用。即XmlWebApplicationContext 会为每个HTTP请求创建一个全新的RequestPrecessor对象,当请求结束后,该对象的生命周期即告结束,如同java web中request的生命周期。当同时有100个HTTP请求进来的时候,容器会分别针对这10个请求创建10个全新的RequestPrecessor实例,且他们相互之间互不干扰,简单来讲,request可以看做prototype的一种特例。
③session:session只用于web程序,通常是和XmlWeb-
ApplicationContext共同使用。对于web应用来说,放到session中最普遍的就是用户的登录信息,对于这种放到session中的信息,Spring容器会为每个独立的session创建属于自己的全新的UserPreferences实例,比request scope的bean会存活更长的时间,其他的方面没区别。
④singleton单例:默认值,容器初始化时创建bean实例,在整个容器的生命周期内只创建一个bean,单例的。
配置Bean-知识点14:使用外部属性文件
在XML配置文件里配置Bean时,有时需要在Bean的配置里混入系统部署的信息(例如:文件路径、数据源配置信息等),而这些部署细节实际上需要和Bean配置相分离(通俗来讲就是你XML不可能满足我全部的配置要求,这就需要我新建其他格式的文件来配置这些要求)。
为了解决这种情况,Spring提供了一个PropertyPlaceholderConfigurer的BeanFactory后置处理器,这个处理器允许用户将Bean配置的一部分内容迁移到属性文件properties中,然后可以在bean配置XML文件中使用形式为${var}的变量,PropertyPlaceholderConfigurer从属性文件里去加载属性,并使用这些属性来替换变量。
Spring还允许在属性文件中使用${propName},来实现属性文件之间的相互引用。
这里需要使用context命名空间来完成该功能:


配置Bean-知识点15:SpEL
Spring表达式语言,简称SpEL,是一个支持运行时查询、操作对象图的强大的表达式语言,SpEL使用#{XXXX}来作为定界符,XXXX就是SpEL内容,SpEL为<bean/>属性的动态赋值提供了便利,通过SpEL可以实现如下效果:
通过<bean/>的id来对bean进行引用、调用方法以及引用对象中的属性、计算表达式的值、正则表达式匹配。



|
SpELDemo{age=12, fraction=85.7, name='ZhangSan', address='USA', enabled=false, weight=100, pi='3.141592653589793', foolName='apple', carName='1.5', carWeight=4000, carWeightHeavy=true, carHeigth=true, carFactory='HongQi', carWidth='2M', car=Car{length='5.5', width='2', heigh='1.5', weight=2000}, food=Food{name='apple'}} |
配置Bean-知识点16:IOC容器中Bean的生命周期方法
Spring IOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定时间节点执行个人定制的任务。Spring IOC容器对Bean的生命周期进行管理的过程:
①通过构造器或者工厂方法创建Bean实例;
②为Bean的属性设置值以及对其他Bean的引用;
③调用Bean的初始化方法,初始化方法可以在<bean/>的init-method属性来指定初始化方法;
④Bean可以使用;
⑤当容器关闭时,调用Bean的销毁方法,销毁方法可以在<bean/>的destroy-method属性来指定销毁方法;


配置Bean-知识点17:创建Bean的后置处理器
Bean后置处理器,允许在调用初始化方法init-method前后对Bean进行额外的处理。Bean后置处理器对IOC容器里的所有Bean实例逐一处理,而非单一实例,典型应用就是检查Bean属性的正确性或者根据特定的标准更改Bean的属性。
对Bean后置处理器而言,需要实现BeanPostProcessor接口,在初始化方法init-method被调用前后,Spring将把每个Bean实例分别传递给上述接口的以下2个方法:
postProcessAfterInitialization
postProcessBeforeInitialization
当添加Bean后置处理器后,Spring IOC容器对Bean的生命周期进行管理的过程如下:
①通过构造器或工厂方法创建Bean实例;
②为Bean的属性设置值和对其他Bean的引用;
③将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization方法;
④调用Bean的init-method指定的方法;
⑤将Bean实例传递给Bean后置处理器的postProcessAfterInitialization方法;
⑥Bean可以使用;
⑦当容器关闭时,调用Bean 的destroy-method指定的方法;



注意:
①后置处理器在配置<bean/>的时候,不需要配置id属性,因为IOC容器自动识别是一个PostProcessor处理器;
②这里的beanname取自<bean/>的id属性。
配置Bean-知识点18:通过自定义工厂方法配置Bean
通过工厂方法配置Bean,可以分为2类:
①静态工厂方法:调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中。当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节。
要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂方法的类,同时再factory-method属性里指定工厂方法的名称,最后再使用<constrctor-arg/>元素来为该方法传递方法参数。




注意:
这里在使用<constrctor-arg/>时,是基于静态工厂方法getProduct的,而不是new Product()的。
另外,class指向的工厂方法类ProductStaticFactory,但在getBean的时候强制类型转换的则是Product。
②实例工厂方法:将对象的创建过程封装到另外一个对象实例的方法里。当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节。
要声明通过实例工厂方法创建的Bean,步骤如下:
- 在bean的factory-bean属性里指定拥有该工厂方法的Bean;
- 在factory-method属性里指定该工厂方法的名称;
- 使用construtor-arg元素来为工厂方法传递方法参数;




配置Bean-知识点19:通过FactoryBean配置Bean
知识点18的工厂类,是开发人员自定义的工厂类,但FactoryBean则是Spring自带的工厂类。FactoryBean相比于自定义工厂类的优点就是:方便使用其他已经定义好的Bean。




配置Bean-知识点20:基于注解方式来配置Bean
从知识点1~知识点19,虽然相比于过去,IOC配合XML文件减轻了很多工作量,但是,这个XML敲起来,真的很繁琐,例如编写id,class中编写全类名,还等其他各种属性。
为了进一步简化配置,让开发者把更多精力放到开发上,而不是配置上,Spring使用了注解方式来取代XML配置。
使用注解来取代XML配置,无外乎2个方面:
①基于注解配置Bean;
②基于注解来装配Bean的属性;
配置Bean-知识点21:基于注解配置Bean
现在说一下Spring注解的几个重点:
①在classpath中扫描组件:组件扫描指的是Spring能够从classpath下自动扫描,来侦测、实例化具有特定注解的组件。这些特定注解包括:
@Component:标识一个受Spring管理的组件;
@Repository:标识持久层组件;
@Service:标识服务层组件;
@Controller:标识表现层组件;
对于这些被扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值来标识组件的名称。
当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>:
1>对base-package属性指定一个需要扫描的基类包,这时Spring容器将会扫描这个基类包以及子包中的所有类,当需要扫描多个包时,可以用逗号进行分隔;
2>如果仅仅希望扫描特定的类,而非基包下的所有类,可使用resource-pattern属性来过滤特定的类;
3><context:include-filter/>子节点表示要包含的目标类;
4><context:exclude-filter/>子节点表示要排除在外的目标类;
5><context:component-scan>下可以包含多个<context:include-filter/>和<context:exclude-filter/>子节点;








<context:include-filter/>和<context:exclude-filter/>子节点能支持多种类型的过滤表达式:
|
类别 |
说明 |
示例 |
|
annotation |
所有标注了XXXAnnotation的类。该类型采用目标类是否标注了某个注解来进行过滤 |
com.suntj.XXXAnnotation |
|
assignable
|
所有继承或扩展XXXService的类。该类型采用目标类是否继承或者扩展某个特定类进行过滤 |
com.suntj.XXXService |
|
aspectj |
所有类名以Service结束的类以及继承或扩展它们的类。该类型采用AspectJ表达式进行过滤 |
com.suntj.*Service+ |
|
regex |
所有xx.xxx.xx包下的类。该类型采用正则表达式根据类的类名进行过滤。 |
com.\suntj.\anno\.* |
|
custom |
采用XXXTypeFilter通过代码的方式定义过滤规则。该类必须实现com.springframework.core.type.TypeFilter接口。 |
com.suntj.XXXTypeFilter |
annotation



+++++++++++++++++++++++++++++++++++++++++++++++++++++++


assignable



配置Bean-知识点22:基于注解来装配Bean的属性
<context:component-scan/>元素还会自动注册Autowired-
AnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired、@Resource、@Inject注解的属性。
@Autowired注解:自动装配具有兼容类型的单个Bean属性。具体细节如下:
- 构造器、普通字段(即使是非public)、一切具有参数的方法都可以应用@Autowired注解;
- 默认情况下,所有使用@Autowired注解的属性都需要被初始化,但是,当Spring找不到匹配的Bean来装配属性时,会抛出异常,如果想要某一属性允许不被初始化,可以设置@Autowired注解的required属性为false;
- 默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作,此时可以在@Qualifier注解里提供Bean的名称,Spring允许对方法的入参标注@Qualifier来指定注入的Bean名称(当然,也可以使用属性名与value属性名来匹配);
- @Autowired注解也可以用在数组类型的属性上,此时Spring将会把所有匹配的Bean进行自动装配;
- @Autowired注解也可以用在集合属性上,此时Spring读取该集合的类型信息,然后自动装配所有与之兼容的Bean;
- @Autowired注解也可以用在java.util.Map上,如果该Map的key值是String,则Spring将自动装配与之Map值类型兼容的Bean,此时的Bean的名称就作为Map的key值,而Bean就是Map的value值;
|
package com.suntj.spring.annotation.component; import com.suntj.spring.annotation.controller.TestController; import com.suntj.spring.annotation.repository.TestRespository; import com.suntj.spring.annotation.service.ITestService; import com.suntj.spring.annotation.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class TestComponent { @Autowired(required = false) private TestController tController; private TestRespository testRespository; @Autowired public void setTestRespository(TestRespository testRespository) { this.testRespository = testRespository; } /** * 我这里引用的是一个接口ITestService * 而该接口有2个实现类:TestService、TestService2 * 要想解决取舍问题,目前有2个解决方法: * 方法1:ITestService变量的名字,与其中2个Service中某个value相同,那么Spring就会根据变量名去匹配; * 方法2:使用@Qualifier注解来明确匹配哪个Bean,里面填写value值; * */ private ITestService iTestService; @Autowired public void setiTestService( @Qualifier("TestService") ITestService iTestService) { this.iTestService = iTestService; } public void out(){ if(null != tController){ tController.out(); } testRespository.out(); iTestService.out(); System.out.println("TestComponent out....."); } } |
配置Bean-知识点23:泛型依赖注入
Spring4.X中可以为子类注入子类对应的泛型类型的成员变量的引用;





配置Bean-知识点24:所编写的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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 指定Spring IOC容器扫描的包 resource-pattern="component/*.class"指的是,仅仅扫描component子包下的所有类 --> <context:component-scan base-package="com.suntj.spring.annotation"> <!-- 不包含org.springframework.stereotype.Component注解的类 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/> --> <!-- 只包含org.springframework.stereotype.Component注解的类 如果使用自定义的filter,还需要把use-default-filters设置为false,意思是,不用Spring自带的filter, 要用context:include-filter指定的filter <context:include-filter>需要use-default-filters属性一起配合使用 <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> --> <!-- 只包含com.suntj.spring.annotation.service.ITestService实现类 <context:include-filter type="assignable" expression="com.suntj.spring.annotation.service.ITestService"/> --> </context:component-scan> <!-- 基于context命名空间,借助PropertyPlaceholderConfigurer来读取properties文件中的信息 --> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.suntj.spring.bean.DataSource" p:user="${user}" p:ip="${ip}" p:password="${password}" p:port="${port}"></bean> <bean id="persion" class="com.suntj.spring.bean.Persion"> <property name="name" value="ZhangSan"/> <property name="age" value="30" /> <property name="address" value="China" /> <!-- 这是普通的Bean引用--> <property name="car" ref="car"/> <!-- 级联属性,即car的weight属性 --> <property name="car.weight" value="3600"/> <!-- 这是内部Bean <property name="car"> <bean class="com.suntj.spring.bean.Car"> <constructor-arg index="0" value="2m"/> <constructor-arg index="1" value="1.5m"/> <constructor-arg index="2" value="1.5m"/> </bean> </property> --> <!-- 设置为null值 <property name="car"><null/></property> --> </bean> <bean id="car" class="com.suntj.spring.bean.Car"> <constructor-arg index="0" value="2m"/> <constructor-arg index="1" value="1.5m"/> <constructor-arg index="2" value="1.5m"/> </bean> <bean id="car2" class="com.suntj.spring.bean.Car"> <constructor-arg type="java.lang.String" > <value><![CDATA[<2m>]]></value> </constructor-arg> <constructor-arg type="java.lang.String" value="1.5m"/> <constructor-arg type="int" value="2000"/> </bean> <!-- 通过p命名空间,来为Bean属性赋值 <bean id="zhangsan" class="com.suntj.spring.bean.Student"> <property name="name" value="ZhangSan"/> <property name="age" value="11"/> <property name="telphone" value="166****1584"/> </bean> <bean id="lisi" class="com.suntj.spring.bean.Student"> <property name="name" value="LiSi"/> <property name="age" value="12"/> <property name="telphone" value="177****1584"/> </bean> --> <bean id="zhangsan" class="com.suntj.spring.bean.Student" p:age="11" p:name="ZhangSan" p:telphone="166****1584"> </bean> <bean id="lisi" class="com.suntj.spring.bean.Student" p:name="LiSi" p:age="12" p:telphone="177****1584"> </bean> <!-- 利用util schema来设置独立的集合 --> <util:list id="studentes"> <ref bean="zhangsan"/> <ref bean="lisi"/> <bean class="com.suntj.spring.bean.Student"> <property name="name" value="WangWu"/> <property name="age" value="13"/> <property name="telphone" value="188****1584"/> </bean> </util:list> <util:map id="teachers"> <entry key="Jack" value-ref="zhangsan"/> <entry key="Lorry" value-ref="lisi"/> </util:map> <util:properties id="teacherPro"> <prop key="Jack">Ha_Fo</prop> <prop key="Lorry">Qing_Hua</prop> </util:properties>
<bean id="teacher" class="com.suntj.spring.bean.Teacher" p:studentes-ref="studentes" p:teacherPro-ref="teacherPro" p:teachers-ref="teachers"> <!-- 初始化java.util.List类型的属性 <property name="studentes" ref="studentes"> <list> <ref bean="zhangsan"/> <ref bean="lisi"/> <bean class="com.suntj.spring.bean.Student"> <property name="name" value="WangWu"/> <property name="age" value="13"/> <property name="telphone" value="188****1584"/> </bean> </list> </property> --> <!-- 初始化java.util.Map类型的属性 <property name="teachers" ref="teachers"> <map> <entry key="Jack" value-ref="zhangsan"/> <entry key="Lorry" value-ref="lisi"/> </map> </property> --> <!-- 初始化java.util.Properties类型的属性 <property name="teacherPro" ref="teacherPro"> <props> <prop key="Jack">Ha_Fo</prop> <prop key="Lorry">Qing_Hua</prop> </props> </property> --> </bean> <bean id="autowireA" class="com.suntj.spring.bean.AutowireA" p:name="AutowireA"/> <bean id="autowireB" class="com.suntj.spring.bean.AutowireB" p:name="AutowireB"/> <bean id="Tautowire" class="com.suntj.spring.bean.Autowire" autowire="byType"/> <!-- 通过parent属性来继承parent的配置,这里只重写了name属性,其他属性与parent一致 --> <bean id="parent" class="com.suntj.spring.bean.Parent" abstract="true" p:name="parent"> </bean> <bean id="children" class="com.suntj.spring.bean.Parent" parent="parent" p:name="children"> </bean> <!-- 依赖 --> <bean id="food" class="com.suntj.spring.bean.Food" p:name="apple"> </bean> <bean id="people" class="com.suntj.spring.bean.People" depends-on="food"> </bean>
<!-- SpEL表达式举例 --> <bean id="car3" class="com.suntj.spring.bean.Car"> <property name="weight" value="2000"/> <property name="length" value="5.5"/> <property name="width" value="2"/> <property name="heigh" value="1.5"/> </bean> <bean id="spELDemo" class="com.suntj.spring.bean.SpELDemo"> <!-- SpEL表示字面值 --> <!-- 整数 --> <property name="age" value="#{12}"/> <!-- 小数 --> <property name="fraction" value="#{85.7}"/> <!-- 科学计数法 --> <property name="weight" value="#{1e2}"/> <!-- 字符串:注意单双引号 --> <property name="name" value="#{'ZhangSan'}"/> <property name="address" value='#{"USA"}'/> <!-- 布尔值 --> <property name="enabled" value="#{false}"/> <!-- SpEL引用Bean、属性、方法 --> <!-- 引用其他对象:通过使用SpEL表达式来注入food实例,可以替换ref属性 --> <property name="food" value="#{food}"/> <!-- 引用其他对象的属性,即便是private修饰的属性 --> <property name="foolName" value="#{food.name}"/> <!-- 调用其他方法、其他方法的链式操作 --> <property name="car" value="#{car3}"/> <property name="carName" value="#{car3.getHeigh().toString()}"/> <!-- 支持算数运算符:+ - * / % ^ --> <property name="carWeight" value="#{car3.getWeight() * 2}"/> <!-- 连接字符串:用+来连接字符串 --> <property name="carWidth" value="#{T(java.lang.String).valueOf(car3.getWidth().toString()) + 'M'}"/> <!-- 比较运算法:> < == >= <= lt gt eq le ge --> <property name="carWeightHeavy" value="#{car3.getWeight() > 100}"/> <!-- 逻辑运算符:and or not | --> <property name="carHeigth" value="#{car3.getHeigh().equals('1.5') and car3.getWeight() == 2000}"/> <!-- if-else运算符: XXX?YYY:ZZZZ XXX?:ZZZZ --> <property name="carFactory" value="#{car3.getWeight() == 2000 ? 'HongQi':'XueFuLan'}"/> <!-- 正则表达式:matches等等 --> <!-- 调用静态方法或者静态属性:必须通过T()来调用一个类的静态方法,T()方法返回一个Object,然后再去调用该Object的静态方法和属性 --> <property name="pi" value="#{T(java.lang.String).valueOf(T(java.lang.Math).PI)}"/> </bean> <!-- Bean的生命周期中自定义函数 --> <bean id="beanLife" class="com.suntj.spring.bean.BeanLife" init-method="init" destroy-method="destroy"> <property name="name" value="bean-life-cycle"/> </bean> <!-- 配置后置处理器 <bean class="com.suntj.spring.bean.MyBeanPostProcess"> </bean> --> <!-- 通过静态工厂方法来配置bean,不是配置静态工厂方法实例,而是配置bean实例 class属性指向静态工厂方法所属的全类名com.suntj.spring.bean.ProductStaticFactory factory-method属性指向静态工厂方法的名字 constructor-arg:如果工厂方法需要传入参数,则使用该属性来配置参数,注意是工厂方法需要参数就要配置该属性,至于构造函数无所谓; --> <bean id="productByStatic" class="com.suntj.spring.bean.ProductStaticFactory" factory-method="getProduct"> <constructor-arg type="java.lang.String" value="product_static"/> </bean> <!-- 通过实例工厂方法来配置bean,需要创建工厂本身,再去调用工厂的实例方法来返回bean实例 factory-bean属性指向实例工厂方法所属的bean factory-method属性指向实例工厂方法的名字 constructor-arg:如果工厂方法需要传入参数,则使用该属性来配置参数,注意是工厂方法需要参数就要配置该属性,至于构造函数无所谓; --> <!-- 第一步:先配置实例工厂Bean --> <bean id="productInstanceFactory" class="com.suntj.spring.bean.ProductInstanceFactory"> </bean> <!-- 第二步:通过实例工厂方法来配置Bean --> <bean id="product" factory-bean="productInstanceFactory" factory-method="getProduct"> <constructor-arg type="java.lang.String" value="product_instance"/> </bean> <!-- 通过FactoryBean来配置bean实例 class属性指向FactoryBean的全类名com.suntj.spring.bean.ProductFactoryBean property配合的是FactoryBean的属性 最后还是调用的FactoryBean.getObject方法 --> <bean id="productByFactoryBean" class="com.suntj.spring.bean.ProductFactoryBean"> <property name="productName" value="product_factorybean"/> </bean> </beans> |
本文深入探讨Spring框架中的IOC(控制反转)和DI(依赖注入)概念,讲解Bean的配置方式、容器类型、依赖注入策略、作用域、生命周期管理等核心知识点。同时,介绍了如何使用注解简化配置,以及Spring4.x中的新特性。
552

被折叠的 条评论
为什么被折叠?



