Spring-IOC/DI-1
来源:互联网 发布:解码矩阵和数字矩阵 编辑:程序博客网 时间:2024/06/05 20:34
- 一 Spring基础
- Eclipse安装
- 安装过程
- 导入jar包
- Spring HelloWorld程序
- 1 HelloWorld类
- 2 不使用Spring的测试代码
- 3 配置xml文件
- 4 使用Spring的HelloWorld程序
- 二 Spring原理IOC和DI
- 名词解释
- 举例理解
- IOC的前生
- 分离接口与实现
- 工厂模式
- IOC容器
- 三 Spring Bean的配置
- Bean配置简介
- 1 Bean的配置形式
- 2 Bean的配置方式
- 3 IOC容器
- 4 依赖注入的方式
- IOC容器
- 通过IOC容器获取Bean
- Bean的xml配置
- 1 属性的依赖注入的方式
- 2 字面值注入
- 3 Bean之间的引用配置
- 4 内部Bean
- 5 注入参数详解null值和级联属性
- 6 集合属性
- 7 配置map属性值
- 8 Properties
- 9 使用utility schema定义集合
- 10 使用p命名空间
- 11 自动装配
- 12 bean之间的关系继承依赖
- 13 配置Bean的作用域
- 14 使用外部属性文件
- Spring表达式语言 SpEL
- 1 SpEL简介
- 2 SpEL字面量
- 3 引用其他对象
- 4 引用其他对象的属性
- 5 运算符
- 6 调用静态方法或静态属性 T
- IOC容器中Bean的生命周期
- 1 Bean的生命周期管理过程
- 2 创建bean后置处理器
- 通过工厂方法静态工厂方法和实例工厂方法配置bean
- 71 静态工厂方法
- 72 实例工厂方法
- FactoryBean配置方式
- 基于注解的方式配置bean
- 1 在classpath中扫描组件
- 2 过滤表达式
- 3 泛型依赖注入
- Bean配置简介
- 一 Spring基础
一. Spring基础
1. Eclipse安装
准备工作:
1. Spring插件
2. Spring jar包
2. 安装过程
help
–> install new software
–> add
–> archive
–> 找到本地spring插件
—> 只点击后缀带有spring IDE
的项 —> 联网更新去掉 —> eclipse重启
3. 导入jar包
把一下jar包加入到工程的classpath当中
- commons-logging-1.1.1.jar–>spring必须依赖的日志包
- beans
- context
- core
- expression
4. Spring HelloWorld程序
- 新建
Java project spring-1
- 新建
lib
–>导入jar
包–>bulid to path
4.1 HelloWorld类
package com.mozart.beans;public class HelloWorld{ private String name; public void setName(String name){ this.name=name; } public void hello(){ System.out.println("hello: "+name); }}
4.2 不使用Spring的测试代码
package com.mozart.beans;public class Main{ public static void main(String[] args){ /1./创建HelloWorld对象 HelloWorld helloWorld=new HelloWorld(); //2.为name属性赋值 helloWorld.setName("mozart"); //3.调用方法 helloWorld.hello(); }}
运行结果:
hello: mozart
4.3 配置xml文件
src
下创建一个Spring Bean configuration File
–>applicationContext.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">> <bean id="helloWorld" class="com.atguigu.spring.beans.helloWorld"> <propertiy name="name2" value="Spring"></propertiy>> </bean>></beans>>
4.4 使用Spring的HelloWorld程序
package com.mozart.beans;public class Main{ public static void main(String[] args){ //1.创建Spring的IOC容器对象 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //2.从IOC容器当中获取Bean实例 HelloWorld helloWorld=(HelloWorld) ctx.getBean("helloWorld"); //3.调用方法 helloWorld.hello(); }}
个人理解
1.ApplicationContext
就代表IOC
容器,它是一个接口。
2.ClassPathXmlApplicationContext
: 表示配置文件在类路径下.创建IOC容器
1. 会对配置文件当中配置的Bean进行初始化
2. 同时会对属性进行复制
二. Spring原理——IOC和DI
1. 名词解释
IOC(Inversion of control)
—->反转控制
1. 传统的资源查找方式:组件向容器发起请求查找资源。
2. IOC
: 容器主动地将资源推送给管理的组件。
DI(Dependency Injection)
—->依赖注入(和反转控制是一个意思)
2. 举例理解
需求: 容器中有两个类A和B。B中有个属性a依赖A。
要求获取B对象。
传统的方式:
A a=getA();B b=getB();b.setA(a);
IOC容器的方式:
容器自动把关联关系建立好了。
3. IOC的前生
- 分离接口与实现
- 工厂模式
- 采用反转控制
举例一个需求: ReportService
类要用到报表生成器ReportGenerator
的接口。 ReportGenerator
的接口有两个实现类PDFReportGenerator
实现类 HtmlReportGenerator
实现类
1. 分离接口与实现
缺点: 耦合性太高
2. 工厂模式
缺点: 代码实现复杂
3. IOC容器
自动化方式,stay foolish!
三. Spring Bean的配置
1. Bean配置简介
1.1 Bean的配置形式
- 基于xml配置文件的方式
- 基于注解的方式
1.2 Bean的配置方式
- 通过全类名(反射)
- 通过工厂方法(静态工厂方法&实例工厂方法)
- FactoryBean
1.3 IOC容器
- BeanFactory
- ApplicationContext
1.4 依赖注入的方式
- 属性注入
- 构造器注入
2. IOC容器
在SpringIOC
容器读取Bean
配置,创建Bean
之前,必须要对IOC
容器进行初始化。只有对IOC容器初始化实例化完成了,
才能够从IOC
容器当中获取Bean
实例并使用。
Spring提供了两种类型的IOC
容器的实现方式:
BeanFactory
:Spring
框架的基本设施,IOC
容器的基本实现。ApplicationContext
提供了更多高级特性,是BeanFactory
的子接口。几乎所有的场合都使用ApplicationContext而不是BeanFactory.ConfigurableApplicationContext
是ApplicationContext
的子接口。ConfigurableApplicationContext
中有新的功能,比如refresh()
,close()
。让容器具有启动,刷新,关闭的功能。ConfigurableApplicationContext
有两个主要的实现类ClassPathXmlApplicationContext
:从类路径下加载配置文件FileSystemXmlApplicationContext
: 从文件系统当中加载配置文件。
ApplicationContext
在初始化的时候就实现了所有单例的Bean
。
非单例Bean
将在Bean
的作用域的时候再说。
WebApplicationContext
是专门为Web应用而准备的。
3. 通过IOC容器获取Bean
BeanFactory
当中具有获取Bean
的方法。 ListableBeanFactory
是继承了BeanFactory
。 ApplicationContext
是实现了ListableBeanFactory
所以,ApplicationContext
也具有了获取Bean
的方法。
通过ID: ID能够唯一定位Bean
new ClassPathXmlApplicationContext("applicationContext.xml").getBean("Bean的id");
通过类型class: 不能唯一定位,使用它要求Bean在容器中是唯一的。
new ClassPathXmlApplicationContext("applicationContext.xml").getBean(HelloWorld.class)
4. Bean的xml配置
id: 通过id来应用Bean,id必须是唯一的。
class: Bean的全类名,通过反射的方式在IOC容器当中创建Bean的实例,要求Bean当中有无参构造器
4.1 属性的依赖注入的方式
Spring
支持3种
依赖注入的方式
1.属性注入: 通过setter
方法为Bean
的属性注入值或者注入引用,开发当中最常用
<property name="name" value="Spring"></property>
2.构造器注入: 不提供setter
方法,通过构造器初始化的操作进行类中属性赋值。
没有name属性
<constructor-arg value="Audi" index="0"></constructor-arg> <constructor-arg value="Shanghai" index="1"></constructor-arg> <constructor-arg value="300000" index="2"></constructor-arg>
这样写很容易产生歧义的。可能很多赋值都匹配一个构造器的。
解决方法如下:
<constructor-arg value="Audi" type="java.lang.String"></constructor-arg><constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg><constructor-arg value="300000" type="double"></constructor-arg><constructor-arg type="int"> <value>250</value></constructor-arg>
属性值可以用value属性也可以使用value子节点进行赋值.
4.2 字面值注入
value
表示的字面值
字面值: 可以用字符串表示的值,可以通过元素标签或者value属性进行注入。
基本数据类型及其封装类,String类型都可以采用字面值注入的方式进行注入。
若字面值当中包含一些特殊字符的话,可以使用<![CDATA[]]>
把字面值包裹起来。
如下:
<constructor-arg index="1"> <value><!CDATA[<Shanghai^>]></value></constructor-arg>
4.3 Bean之间的引用配置
<bean id="person" class="com.atguigu.spring.beans.Person"> <property name="name" value="tom"></property> <property name="age" value="tom"></property> <!--可以使用property的ref属性建立bean之间的引用关系--> <property name="car" ref="car2"></property> <property name="car"> <ref bean="car2" /> </property></bean>
组成应用程序的Bean需要相互协助.
在Bean的配置文件当中,可以通过元素或者ref属性为Bean的属性或者构造器参数指定对Bean的引用。
也可以在属性或者构造器的内部包含一个bean的声明,这样的Bean称之为内部Bean。
4.4 内部Bean
<bean id="person" class="com.atguigu.spring.beans.Person"> <property name="name" value="tom"></property> <property name="age" value="20"></property> <!--可以使用property的ref属性建立bean之间的引用关系--> <property name="car" ref="car2"></property> <property name="car"> <bean class="com.atguigu.spring.beans.Car"> <contructor-arg value="Ford"></contructor-arg> <contructor-arg value="Changan"></contructor-arg> <contructor-arg value="200000" type="double"></contructor-arg> </bean> </property></bean>
内部Bean不用写id,不能够被外部引用的。
<bean id="person2" class="com.atguigu.spring.beans.Person"> <contructor-arg value="jerry"></contructor-arg> <contructor-arg value="25"></contructor-arg> <contructor-arg ref="car2"></contructor-arg></bean>
4.5 注入参数详解—null值和级联属性
可以使用专用的<null/>
元素标签为Bean的字符串或者其他对象类型的属性赋值为null值。
其实没有多大的意思,因为引用类型的默认都是null。
<bean id="person2" class="com.atguigu.spring.beans.Person"> <contructor-arg value="jerry"></contructor-arg> <contructor-arg value="25"></contructor-arg> <contructor-arg><null/></contructor-arg></bean>
Spring
支持级联属性的配置。(Bean当中的Bean的属性赋值)
注意,属性需要先初始化后,才可以为级联属性赋值。否则异常,和Struts2
不同。
<bean id="person2" class="com.atguigu.spring.beans.Person"> <contructor-arg value="jerry"></contructor-arg> <contructor-arg value="25"></contructor-arg> <contructor-arg ref="car"></contructor-arg> <!--为级联属性赋值,这要求car这个类当中有setPrice方法--> <property name="car.price" value="300000"></property></bean>
4.6 集合属性
一个人可以有好多辆车,人对象,车对象,怎么在xml当中配置bean。
使用节点为list的属性赋值
<list> <set> <map>
标签配置集合属性。
<bean id="person2" class="com.atguigu.spring.beans.Person"><property name="name" value="Mike"></property><property name="age" value="27"></property><property name="cars"> <list> <ref bean="car" /> <ref bean="car2" /> </list></property></bean>
4.7 配置map属性值
使用map
节点以及map
的entry
子节点配置map
类型的成员变量。
<bean id="person2" class="com.atguigu.spring.beans.Person"><property name="name" value="Mike"></property><property name="age" value="27"></property><property name="cars"> <map> <entry key="AA" value-ref="car"></entry> <entry key="BB" value-ref="car2"></entry> </map></property></bean>
4.8 Properties
Properties
是HashTable
的一个子类,HashTable
是Map
的一个实现类.
到时候和hibernate
可以整合。
使用props
和prop
子节点来为properties
属性赋值.
<bean id="datasource" class="com.atguigu.spring.beans.collection.datasource"> <property name="properties"> <props> <prop key="user">root</prop> <prop key="password">1234</prop> <prop key="jdbcurl">jdbc:mysql:///test</prop> <prop key="driverClass">com.mysql.jdbc.Driver</prop> </props> </property></bean>
4.9 使用utility schema
定义集合
配置单例的集合Bean
,以供多个Bean
进行引用
引入新的util
命名空间。
<util:list id="cars"> <ref bean="car" /> <ref bean="car2" /></util:list><bean id="person4" class="com.atguigu.spring.beans.collection.Person"><property name="name" value="Jack"></property><property name="age" value="29"></property><property name="cars" ref="cars"></property></bean>
4.10 使用p命名空间
在Spring2.5
当中引入了新的命名空间,可以通过比较简化的方式配置bean
属性。
需要先导入p命名空间。
相对于传统的配置方式,更加简洁。
<bean id="person5" class="com.atguigu.spring.beans.collection.Person" p:name="Queen" p:age="30" p:car-ref="cars"></bean>
4.11 自动装配
Spring IOC
容器可以自动装配Bean
,需要做的就是仅仅是在<bean>
的autowire
属性当中指定自动装配的模式。
byType
(根据类型自动装配):
若IOC容器中有多个与目标Bean
类型一致的Bean
,
在这种情况下,Spring
将无法判定哪个Bean
最合适该属性
,所以不能执行自动装配。
byName
(根据名称自动装配):
必须将目标Bean
的名称和属性设置的完全相同。
constructor
(通过构造器自动装配):
将Bean
中存在多个构造器的时候,此种装配方式将会很复杂,不推荐使用.
举例说明 person
对象有name
,address
对象(city,street)
,car
对象(brand,price)
beansautowire.xml
代码
<bean id="address" class="com.atguigu.spring.beans.autowire.Address" p:city="beijing" p:street="HuiLongGuan"></bean><bean id="car" class="com.atguigu.spring.beans.autowire.Car" p:brand="Audi" p:price="300000"></bean><bean id="person" class="com.atguigu.spring.beans.autowire.person" p:name="Tom" p:address-ref="address" p:car-ref="car"><bean id="person" class="com.atguigu.spring.beans.autowire.person" p:name="Tom" autowire="byType"></bean>
byName
:根据bean
的名字和当前bean
的setter
方法的属性名进行自动装配,
若有匹配的,则进行自动装配,若没有匹配的,则不进行装配。
byType
根据Bean
的类型和当前bean
的属性的类型进行自动装配,若IOC容器当中有1个以上的类型匹配的bean,则抛出异常。
在Bean配置文件里设置autowire
属性进行自动装配将会装配Bean的所有属性,
然而,若只希望装配个别属性的时候,autowire
属性就不够灵活了。
autowire
属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼而有之。
一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些。
但是在整合第三方框架的时候会使用autowire
,会给我们带来一些方便。
4.12 bean之间的关系:继承/依赖
Spring
允许继承bean
的配置,被继承的bean
称之为父bean
,继承这个父bean
的bean
称之为子bean
。
子bean
从父bean
中继承配置,包括bean
的属性配置
子bean
可以覆盖从父bean
当中继承过来的配置。
父bean
可以作为配置模板,也可以作为bean
实例,若只想把父bean
作为模板,可以设置<bean>
的abstract
属性为true
,这样spring
将不会实例化这个bean
并不是bean
元素里头的所有的属性都会被继承,比如 autowire
,abstract
等。
也可以忽略父bean
的class
属性,让子bean
指定自己的类,而共享相同的属性配置,
但此时abstract
必须设为true
。
如果把bean
的class
属性去掉,就必须加上abstract=true
。
<bean id="address" class="com.atguigu.spring.beans.autowire.address"p:city="Beijing" p:street="WuDaoKou" abstract="true"></bean><bean id="address2" p:street="DaZhongSi" parent="address"></bean><bean id="person" class="com.atguigu.spring.beans.autowire.person" p:name="Tom" p:address-ref="address2" depends-on="car"></bean>
Spring
允许用户通过depends-on
属性设定bean
前置依赖的bean
。
前置依赖的bean
会在本bean
实例化之前创建好。
如果前置依赖于多个bean
,则可以通过都好,空格或的方式配置bean的名称。
4.13 配置Bean的作用域
使用Bean
的scope
属性来配置bean
的作用域 singleton
: 默认值,容器初始时创建bean
实例,在整个容器的生命周期内只创建了这一个bean
,是单例的。 prototype
:原型的,容器初始化的时候并没有创建bean
实例,你请求bean
的时候,容器就创建一个bean
,再请求再创建,是不一样的bean
实例.
<bean id="Car" class="com.atguigu.spring.bean.beanscope" scope="singleton"><property name="brand" value="Audi"></property><property name="price" value="200000"></property></bean>
4.14 使用外部属性文件
在配置文件里配置bean
的时候,有时候需要在bean
的配置里混入系统部署的细节信息(例如:文件路径,数据源配置信息等)
而这些部署细节实际上需要和bean
的配置相分离。
Spring
提供了一个PropertyPlaceholderConfigurer
的BeanFactory
后置处理器。
这个处理器允许用户将bean
配置的部分内容外移到属性文件当中。
可以在bean
配置文件里头使用形式为${var}
的变量
PropertyPlaceholderConfigurer
从属性文件里头加载属性,
并使用这些属性来替换变量。
Spring
还允许在属性文件里头使用$(propName)
,以实现属性之间的相互作用。
bean-property.xml配置一个数据源
导入c3p0-0.9.1.2.jar
加入mysql的驱动mysql-connector-java-5.1.7-bin.jar
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="root"></property> <property name="password" value="1230"></property> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///test"></property></bean>
<!-- 导入属性文件 --><context:property-placeholder location="classpath:db.properties" /><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="$(user)"></property> <property name="password" value="$(password)"></property> <property name="driverClass" value="$(driverClass)"></property> <property name="jdbcUrl" value="$(jdbcUrl)"></property></bean>
5. Spring表达式语言 :SpEL
5.1 SpEL简介
Spring
表达式语言(简称SpEL
):
是一个支持运行时查询和操作对象的强大的表达式语言
语法类似于EL
: SpEL
使用#{}
作为定界符,所有在大括号里头的字符都被认为是SpEL
SpEL
为bean
的属性进行动态赋值提供了便利。
通过SpEL
可以实现:
- 通过
bean
的id
对bean
进行引用 - 调用方法以及引用对象中的属性
- 计算表达式的值
- 正则表达式的匹配
5.2 SpEL字面量
字面量的表示:
整数: <property name="count" value="#{5}"></property>
小数: <property name="count" value="#{89.7}"></property>
科学计数法: <property name="count" value="#{1e4}"></property>
字符串: <property name="count" value="#{'chuck'}"></property>
布尔值: <property name="count" value="#{false}"></property>
如果是仅仅是赋字面值的话用SpEL的意义不大的。
5.3 引用其他对象
<property name="prefix" value="#{prefixGenerator}"></property>
相当于
<property name="prefix" ref="prefixGenerator"></property>
5.4 引用其他对象的属性
<property name="prefix" value="#{prefixGenerator.suffix}"></property>
调用其他方法,还可以链式操作(动态为属性进行赋值)
<property name="prefix" value="#{prefixGenerator.toString()}"></property><property name="prefix" value="#{prefixGenerator.toString().toUpperCase()}"></property>
5.5 运算符
算数运算符:+ - * / %, 加号可以作为字符串的连接符
比较运算符:< > == <= >= lt gt eq le ge
逻辑运算符: and or not
if-else运算符: ?():()
正则表达式:matches
5.6 调用静态方法或静态属性: T()
<property name="prefix" value="#{T(java.lang.Math).PI}"></property>
<bean id="address" class="com.atguigu.spring.beans.spel.Address"> <property name="city" value="#{'Beijing'}"></property> <property name="street" value="Wudaokou"></property></bean>
6. IOC容器中Bean的生命周期
SpringIOC
容器可以管理Bean
的生命周期,Sprirng
允许在Bean
生命周期的特定点执行定制的任务。
6.1 Bean的生命周期管理过程
SpringIOC
容器对Bean
的生命周期进行管理的过程:
- 通过构造器或工厂方法创建bean实例。
- 为bean的属性设置值和对其他bean的引用
- 调用用bean的初始化方法
- bean可以使用了
- 当容器关闭时,调用bean的销毁方法
在bean的生命里设置init-method
和destroy-method
属性,为bean
指定初始化和销毁方法。
<bean id="car" class="com.atguigu.spring.beans.cycle.Car" init-method="init" destroy-method="destroy"> <property name="brand" value="Audi"></property></bean>
6.2 创建bean后置处理器
bean
后置处理器允许在调用初始化方法前后对Bean
进行额外的处理。
bean
后置处理器对IOC
容器里的所有bean
实例注意处理,
而非是单一实例。
其典型应用是:检查bean
属性的正确性或根据特定的标准更改bean
的属性。
对bena后置处理器而言,需要实现interface beanPostProcessor
接口。
在初始化方法被调用前后,Spring
将把每个bean
实例分别传递给上述接口的以下两个方法:
postProcessAfterInitialization(Object bean,String beanName);postProcessBeforInitialization(Object bean,String beanName);
Spring IOC
容器对bean的生命周期进行管理的过程 :
- 通过构造器或工厂方法创建bean实例。
- 为bean的属性设置值和对其他bean的引用
- 将bean实例传递给Bean后置处理器的postPorcessBeforInitialization方法
- 调用bean的初始化方法
- 将bean实例传递给Bean后置处理器的postPorcessAfterInitialization方法
- bean可以使用了
- 当容器关闭的时候,调用bean的销毁方法
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="car" class="com.atguigu.spring.beans.cycle.Car" init-method="init" destroy-method="destroy"> <property name="brand" value="Audi"></property></bean><!-- 配置bean的后置处理器 --><bean class="com.atguigu.spring.beans.cycle.MyBeanPostProcessor"></bean></beans>
后置处理器类代码
package com.atguigu.spring.beans.cycle;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization" + bean + "," + beanName); //可以检查bean,这是通用的。 //可以创建一个新的bean,然后返回 return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization" + bean + "," + beanName); return null; }}
后置处理器类代码
public class MyBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization" + bean + "," + beanName); //可以检查bean,这是通用的。 //可以创建一个新的bean,然后返回 if("car".equals(beanName)){ //....对bean进行过滤 } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization" + bean + "," + beanName); Car car=new Car(); car.setBrand("Ford"); return car; }}
7. 通过工厂方法(静态工厂方法和实例工厂方法)配置bean
上面都是通过全类名反射配置bean
7.1 静态工厂方法
直接调用某一个类的静态方法就可以返回bean的实例
工厂类代码
public class StaticFactory{ private static Map<String,car> cars=new HashMap<String,Car>(); static{ cars.put("audi",new Car("audi",300000)); cars.put("ford",new Car("ford",400000)); } //静态工厂方法 public static Car getCar(String name){ return cars.get(name); }}
xml配置代码
<!--通过静态工厂方法来配置bean,不是配置静态工厂方法实例,而是配置bean实例--> <!--class属性指向静态工厂方法的全类名,factory-mehod指向静态工厂方法的方法名字 如果工厂方法需要传入参数,则使用constructor-arg来传递参数 --><bean id="car1" class="com.lingyao.StaticFactory" factory-method="getCar"> <constructor-arg value="audi"></constructor-arg></bean>
7.2 实例工厂方法
实例工厂的方法,也就是先创建工厂本身,再调用工厂的实例方法。
工厂类代码
public class InstanceCarFactory{ private Map<String,Car> cars=null; public InstanceCarFactory(){ cars=new HashMap<String,Car>(); cars.put("audi",new Car("audi",300000)); cars.put("ford",new Car("ford",400000)); } public Car getCar(String name){ return cars.get(name); }}
xml配置代码
<bean id="car1" class="com.lingyao.StaticFactory" factory-method="getCar"> <constructor-arg value="audi"></constructor-arg></bean>
8. FactoryBean配置方式
为什么要用FactoryBean?
配置bean
的时候要用到IOC
容器的其他bean
,用factoryBean
是最合适。
自定义FactoryBean
需要实现Spring
当中的一个接口叫做:FactoryBean
public class CarFactoryBean implements FactoryBean<Car>{ //返回bean的对象 private Stirng brand; public void setBrand(String brand){ this.brand=brand } public Car getObejct() throws Exception{ return new Car("BMW",500000); } //返回bean的类型 public Class<?> getObjectType(){ return Car.class; } public boolean isSingleton(){ return true; }}
通过FactoryBean配置bean实例,class执行FactoryBean的全类名
property是FactoryBean的属性
但返回的实例就是FactoryBean中的getObject方法返回的一个bean
<bean id="car" class="com.lingyao.CarFactoryBean" factory-method="getCar"><property name="brand" value="BMW"></property></bean>
9. 基于注解的方式配置bean
上面所有的配置bean的方式都是基于xml文件的方式进行配置的。
1. 基于注解配置bean
2. 基于注解配置bean的属性
9.1 在classpath中扫描组件
组件扫描(component scanning)
:Spring
能够从classpath
下自动扫描,侦测和实例化具有。特定注解的组件。
特定组件包括: @Component
: 基本注解,标识了一个受Spring管理的组件。 @Respository
: 标识持久层组件 @Service
: 标识服务层(业务层)组件 @Controller
: 标识表现层组件
对于扫描到的组件,Spring
有默认的命名策略:
使用非限定类名,第一个字母小写.
也可以在注解中通过value
属性值标识组件的名称。
当在组件类上使用了特定的注解之后,
还需要在Spring的配置文件中声明 <context:componext-scan>
base-package
属性指定一个需要扫描的基类包, Spring
容器将会扫描这个基类包里及其子包中的所有类。
当需要扫描多个包时,可以使用逗号分隔。
如果仅希望扫描特定的类而非基包下的所有类,
可以使用resource-pattern
属性过滤特定的类,示例:
<context:component-scan base-package="com.atguigu.spring.beans" resource-pattern="autowire/*.class" /><context:include-filter> 子节点表示要包含的目标类<context:exclude-filter> 子节点表示要排除在外的目标类<context:component-scan> 下可以拥有若干个<comtext:include-filter>和<context:exclude-filter>子节点。
比方说有很多包,包中所有的类都用注解标识上了,然后配置了context:component-scan
,就指定扫描那些包。
举例理解:
第一, 建立一个TestObject类,加上注解@
第二, 接口UserRepository
实现类 UserRepositoryImple
implements UserRepostory
注解@Repository
,模拟持久化层
第三: UserService
类,其中有个方法add(){}
方法
注解:@Service
第四: UerController
类,其中有个execute(){}
方法,
注解@Controller
.
创建bean
的配置文件—->beans-annotation.xml
,导入context
命名空间。
<!--指定spring ioc容器扫描的包--><context:component-san base-package="anotation"><bean></bean>
9.2 过滤表达式
<context:include-filter>
和<context:exclude-filter>
支持多种类型的过滤表达式
annotation
: 所有标注了xxxAnnotation
的类
assinable
: 所有继承或扩展xxxService
的类
aspectj
: 所有类名以Service
结束的类以及继承或扩展它们的类。
该类型采用AspejctJ
进行过滤。
regex
:
所有com.atguigu.anno
包下的类。该类型采用正则表达式根据类的类名进行过滤。
custom
:
采用xxxTypeFilter
通过代码的方式定义过滤规则。该类必须实现 org.springframework.core.type.TypeFilter
接口
component–controller-repository-service
<!--指定spring ioc容器扫描的包--><bean> <context:component-san base-package="com.atguigu.spring.beans.anotation"><context:execlude-filter type="annotation" use-default-filter="true" expression="org.springframework.stereotype.Repository" /></bean>
9.3 泛型依赖注入
BaseService —-> @Autowired BaseRepository
BaseRepository
User
UserService extends BaseService —-> @Service
UserRepository extends BaseRepository —-> @Repository
父类泛型之间建立引用的。
BaseService当中有个成员变量,或者方法是关于BaseRepository的。
这个变量或方法用@Autowired来自动装配。
这样,父类泛型之间就建立起了引用了。
子类指定user泛型的Service和UserRepository之间也就自动地建立了引用了。
然后在测试的时候,从IOC容器中拿到userService这个bean。调用其中的方法,就会自动装配对应的Repository子类了。
总结一下:
父类之间的引用关系,对应子类之间自动引用。
子类都用注解交给IOC管理之后,很容易调用对用子类泛型。
- Spring-IOC/DI-1
- Spring 1 IoC 3 DI
- Spring(1)IOC/DI
- spring学习-1-IOC和DI
- 1、Spring框架-IoC与DI
- Spring基础-1-IOC与DI
- Spring模拟(DI,IOC)
- Spring ioc Di概念
- spring IoC与DI
- Spring--IoC和DI
- spring IOC /DI 详解
- spring IOC ,DI原理
- Spring IOC(DI)模拟
- spring--IoC和DI
- Spring 的IoC DI
- Spring IOC/DI 配置
- spring IOC和DI
- 模拟Spring IOC DI
- 实现点击在当前位置画一个黑点,打印出当前点击的坐标
- MySQL--操作数据表4:多表更新
- vb.net 教程 3-7 窗体编程 菜单和工具栏 3 StatusStrip 1
- 扫盲:集线器、网桥、交换机、路由器、网关大解析
- PHP_WAMPServer安装+配置(自定义根目录、多站点、端口)
- Spring-IOC/DI-1
- OpenCV的Mat 等价GDAL的数据(float型)
- Carbondata源码阅读(1)
- Java基础回顾——重难点易错点【1】
- C语言的程序跳转break,continue等
- windows配置Scrapy爬虫框架
- 如何发布新文章到hexo搭建的个人博客
- Linux下编译安装源代码的三个步骤
- PAT (Advanced Level) Practise 1108 Finding Average (20)