1.IOC(控制反转)和DI(依赖注入)
-
IOC
:控制反转,将对象的创建权反转给Spring -
DI
:依赖注入,前提必须有IOC的环境,Spring在管理类的时候会将类的依赖的属性注入(设置)进来 - 面向对象的时候类之间关系:
1.依赖
class A{
}
class B{
public void xxx(A a){}
}2.继承
class A{
}
class B extends A{
}3.集合:has a
2.依赖注入示例
传统操作设置name:
采用DI(依赖注入):
的工厂类
3.工厂结构图
ApplicationContext和BeanFactory的区别
:
- ApplicationContext继承了BeanFactory
- BeanFactory在调用getBean的时候才会生成类的实例,ApplicationContext在加载配置文件的时候就会将Spring管理的类都实例化
3.(老版本)
BeanFactory在调用getBean的时候才会生成类的实例
3.(新版本)
ApplicationContext继承了BeanFactory且在加载配置文件的时候就会将Spring管理的类都实例化,ApplicationContext有两个实现类:
-
ClassPathXMLApplicationContext
:加载类路径下的配置文件 -
FileSystemXMLApplicationContext
:加载文件系统的配置文件
的配置
4.的提示配置
4.1.的配置
4.1.的相关配置
4.1.2.1.<bean>标签的id和name配置
-
id
:使用了约束中的唯一约束
,里面不能出现特殊字符
-
name
:没有使用约束中的唯一约束
(理论上是可以重复的,但实际开发中不能出现,会报错),可以出现特殊字符
(和Struts1框架整合时要用name,因为Struts1中用了特殊字符) -
class
:要生成的实例的类的全路径
4.1.2.的生命周期配置
-
init-method
:Bean被初始化的时候执行的方法 -
destroy-method
:Bean被销毁时执行的方法(Bean是单例创建,工厂关闭)
4.1.2.的作用范围配置(重点)
scope:Bean的作用范围
-
singleton
:默认的,Spring会采用单例模式创建这个对象 -
prototype
:多例模式,用一次new一个 - request:应用在Web项目中,Spring创建这个类以后,将这个类存入到request范围中
- session:应用在Web项目中,Spring创建这个类以后,将这个类存入到session范围中
- globalsession:应用在Web项目中,必须在porlet环境(在一个地方登陆后在其他子网站登陆就不需要再登陆)下使用
的Bean管理
5.中Bean的实例化
5.1.1.静态工厂方法
调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中
,当客户端需要对象时, 只需要简单地调用静态方法,而不同关心创建对象的细节,要声明通过静态方法创建的 Bean,需要在 Bean 的 class 属性里指定拥有该工厂的方法的类,同时在 factory-method
属性里指定工厂方法的名称。最后使用 <constrctor-arg>
元素为该方法传递方法参数
package com.xpu.bean_factory;
import java.util.HashMap;
import java.util.Map;
/**
* 静态工厂方法:直接调用某一个类的静态方法就可以返回一个bean的实例
*/
public class StaticCarFactory {
private static Map<String, Car> cars = new HashMap<>();
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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
<!-- 通过静态方法工厂来配置Bean,注意不是配置静态方法工厂实例,而是Bean实例 -->
<!-- class属性指向静态方法工厂的Class
factory-method属性指向静态工厂的名字
constructor-arg如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car1" class=".bean_factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="audi"></constructor-arg>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
5.1.2.实例工厂方法
将对象的创建过程封装到另外一个对象实例的方法里
, 当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节,要声明通过实例工厂方法创建的 Bean
- 在 bean 的 factory-bean 属性里指定拥有该工厂方法的 Bean
- 在 factory-method 属性里指定该工厂方法的名称
- 使用 construtor-arg 元素为工厂方法传递方法参数
package com.xpu.bean_factory;
import java.util.HashMap;
import java.util.Map;
/**
* 实例工厂的方法,即先需要创建工厂本身,再调用工厂的实例方法,再返回Bean实例
*/
public class InstanceCarFactory {
private static Map<String, Car> cars = null;
public InstanceCarFactory() {
cars = new HashMap<>();
cars.put("audi", new Car("audi",300000));
cars.put("ford", new Car("ford",400000));
}
public Car getCar(String brand) {
return cars.get(brand);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
<!-- 配置工厂的实例 -->
<bean id="carFactory" class=".bean_factory.InstanceCarFactory"></bean>
<!-- 通过实例工厂方法来配置Bean -->
<!-- factory-bean属性指向实例方法工厂的Class
factory-method属性指向实例工厂的名字
constructor-arg如果工厂方法需要传入参数,则使用constructor-arg来配置参数
-->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="ford"></constructor-arg>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
5.1.
实现FactoryBean接口在Spring IOC容器中配置Bean
,Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean。工厂 Bean 跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂 Bean 的 getObject 方法所返回的对象 ,示例如下:
package com.xpu.factory_spring;
import org.springframework.beans.factory.FactoryBean;
//自定义的FactoryBean需要实现Spring提供的FactoryBean接口
public class CarFactoryBean implements FactoryBean<Car> {
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
//返回Bean的对象
@Override
public Car getObject() throws Exception {
return new Car(brand, 500000);
}
//返回Bean的类型
@Override
public Class<?> getObjectType() {
return Car.class;
}
//是否是单例的
@Override
public boolean isSingleton() {
return true;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
<!-- 通过FactoryBean来配置Bean的实例
class执行FactoryBean的全类名
property配置的是FactoryBean的属性,但是返回的FactoryBean的getObject()方法返回的实例
-->
<bean id="car" class=".factory_spring.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5.1.4.基于注解的方式
接下来说说基于注解的方式配置Bean
,这也是常见的方式:
组件扫描(component scanning):Spring能够从classpath下自动扫描,,侦测和实例化具有特定注解的组件,特定组件包括:
-
@Component
:基本注解,标识了一个受 Spring 管理的组件 -
@Respository
:标识持久层组件 -
@Service
:标识服务层(业务层)组件 -
@Controller
;标识表现层组件
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称。当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明需要扫描的包,而且不要忘记声明命名空间<context:component-scan>
:
<context:component-scan base-package=""></context:component-scan>
- 1
base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。当需要扫描多个包时,可以使用逗号分隔,如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern
属性过滤特定的类,示例:
<!-- 可以通过resource-pattern可以指定扫描的资源 -->
<context:component-scan base-package="" resource-pattern="service/*.class" ></context:component-scan>
- 1
- 2
-
<context:include-filter>
子节点表示要包含的目标类 -
<context:exclude-filter>
子节点表示要排除在外的目标类 -
<context:component-scan>
下可以拥有若干个<context:include-filter>
和<context:exclude-filter>
子节点
<!-- context:exclude-filter就是排除哪些类 -->
<context:component-scan base-package="" use-default-filters="false">
<context:exclude-filter type="annotation" expression=""/>
</context:component-scan>
<context:component-scan base-package="" use-default-filters="false">
<context:include-filter type="annotation" expression=""/>
</context:component-scan>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
注意对于那些已经配置了注解的类,想要使自己的过滤器生效,就需要配置一个use-default-filters="false"
要求不要使用默认的过滤器
<context:include-filter>
和 <context:exclude-filter>
子节点支持多种类型的过滤表达式:
类别 | 示例 | 说明 |
---|---|---|
annotation | 所有标注了XxxAnnotation的类,该类型采用目标类型是否标注了某个注解进行过滤 | |
assinable | 继承或者扩展XxxService的类,该类型采用目标类型是否继承或者拓展某个特定的类进行过滤 | |
aspectj | .*Service+ | 所有类名以Service结束及继承或扩展它们的类,该类型采用aspectJ表达式进行过滤 |
regex | .* | 所有包下的类,该类型采用正则表达式根据类名进行过滤 |
custom | 采用XxxTypeFilter通过代码的方式定义过滤规则。该类必须实现接口 |
5.的属性注入
5.2.1.构造方法的方式的属性注入
5.2.方法的方式的属性注入
对象类型属性的注入
类中方法:value是设置普通类型的值,ref用来设置其他类的id或name
- 构造方法方式设置对象类型属性:constructor-arg标签也有ref
- set方法方式设置对象类型属性:用ref
5.2.名称空间属性的注入(Spring2.5以后的版本)
通过引入p名称空间完成属性的注入
,写法如下:
- 普通属性: p:属性名=“值”
- 对象属性: p:属性名-ref=“值”
5.2.的属性注入(Spring3.0以后的版本)
- SpEL:Spring Expression Language,Spring表达式语言
- 语法:#{SpEL}
注入普通属性
注入对象类型属性:
5.3.集合类型的属性注入
/**
* 集合属性的注入
*/
public class CollectionBean {
private String[] arrs;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setArrs(String[] arrs){
this.arrs = arrs;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "CollectionBean{" +
"arrs=" + Arrays.toString(arrs) +
", list=" + list +
", set=" + set +
", map=" + map +
'}';
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
配置文件内容:
<!--Spring集合属性的注入-->
<!--注入数组类型-->
<bean id = "collectionBean" class="">
<!--数组类型和list是一样的-->
<property name="arrs">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<!--注入list集合-->
<property name="list">
<list>
<value>小可爱</value>
<value>小靓仔</value>
<value>小鸡儿</value>
</list>
</property>
<!--注入set集合-->
<property name="set">
<set>
<value>头发</value>
<value>鼻子</value>
<value>耳朵</value>
</set>
</property>
<!--注入map集合-->
<property name="map">
<map>
<entry key="小鸡" value="111"></entry>
<entry key="小猫" value="333"></entry>
<entry key="小狗" value="222"></entry>
</map>
</property>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
注入成功: