目录
Spring Bean
IOC 容器 BeanFactory 和 ApplicationContext
DI 方式 属性注入 和构造器注入
-
bean 配置
- id 必须唯一
- class 全路径,因为是通过反射来构建bean,所以bean中必须有一个无参的构造器。
-
Spring IOC 容器,必须对其进行实例化,才能从IOC容器中获取bean,Spring 提供了2种容器
- ApplicationContext 是BeanFactory的子接口提供了更多的高级特性,面向Spring框架开发者
- ClassPathXmlApplicationContext:从类路径下加载配置文件
- FileSystemXmlApplicationContext:从文件系统加载配置文件
- WebApplicationContext:基于web的
- BeanFactory IOC 基本实现,面向Spring本身。
- 配置是不变的。
-
ConfigurableApplicationContext 扩展了 ApplicationContext 主要增加了2个方法,refresh(),close() 让ApplicationContext具有启动、刷新和关闭上下文的能力
- ApplicationContext 是BeanFactory的子接口提供了更多的高级特性,面向Spring框架开发者
ApplicationContext 在初始化的时候就初始化了所有的单例的bean
getBean
- 利用id
Car car1 = (Car) context.getBean("car1");
- 利用XXX.class 这种需要容器中类唯一,如果两个类ID不同 ,用这种方法会报错。好处是不需要再转型
UserEntity user = context.getBean(UserEntity.class);
- 还有一些不常用的,没有整理。
使用xml配置bean
- 属性注入,<property> 主要是用来注入一些字面值,比如String ,int 等
<!-- 使用property 注入car -->
<bean id="car1" class="com.nina.spring.bean.Car">
<property name="brand" value="Audi"></property>
<property name="price" value="20000"></property>
</bean>
- 构造方法注入, <constructor-arg> 这里主要,注入属性的个数,需要与对应bean中有参的构造器一致,否则会提示没有对应参数的构造器
<!-- 使用构造器 注入 -->
<bean id="car2" class="com.nina.spring.bean.Car">
<constructor-arg type="java.lang.String" value="Toyot"></constructor-arg>
<constructor-arg type="double" value="300000"></constructor-arg>
</bean>
- 如果字面值包含特殊字符可以用 <![CDATA[]]>包裹
<!-- 使用property 注入car3 -->
<bean id="car3" class="com.nina.spring.bean.Car">
<property name="brand">
<value><![CDATA[<SANGTanna&&>]]></value>
</property>
<property name="price" value="20000"></property>
</bean>
- 注入类,使用<ref>
<!-- car1 是之前的car的id ref 用来引用类 -->
<bean id="person1" class="com.nina.spring.bean.Person">
<property name="age" value="20"/>
<property name="name" value="HuangSang"/>
<property name="car" ref="car1"/>
</bean>
- 还可以用使用内部bean
- null 值,使用 <null/>
- 级联属性赋值,属性需要初始化后,才可以使用级联赋值。
<bean id="person1" class="com.nina.spring.bean.Person">
<property name="age" value="20"/>
<property name="name" value="HuangSang"/>
<property name="car" ref="car1"/>
<property name="car.brand" value="MAITeng"></property>
</bean>
- 集合属性 list map 需要使用 entry
<property name="carList">
<list>
<ref bean="car1" />
<ref bean="car2" />
<ref bean="car3" />
</list>
</property>
<property name="carMap">
<map>
<entry key="AA" value-ref="car1"></entry>
<entry key="BB" value-ref="car2"></entry>
</map>
</property>
- properties 使用 pros
<bean id="dataSource" class="com.nina.spring.bean.DataSource">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="pass">shordaao</prop>
</props>
</property>
</bean>
- 配置单例的集合bean,需要导入util命名空间
<util:list id="cars">
<ref bean="car1"/>
<ref bean="car2"/>
</util:list>
<bean id="person2" class="com.nina.spring.bean.Person">
<property name="carList" ref="cars"></property>
</bean>
- p命名空间,需要先导入,
<bean id="person3" class="com.nina.spring.bean.Person" p:age="399" p:car-ref="car3">
</bean>
- 自动装配, 在bean 的属性里面,指定autowire的模式byType,byName
<bean id="person4" class="com.nina.spring.bean.Person" autowire="byType"></bean>
- bean 之间的关系,继承和依赖。子bean可以继承父bean的所有属性,并可以覆盖,父bean,如果只是用作配置模板,可以指定 abstract=“true” , 这样不能实例化,同时,抽象bean,可以不指定 class 属性。
<bean id="address" class="com.nina.spring.bean.Address" p:street="wudaokou">
<property name="city" value="Beijing"></property>
</bean>
<bean id="address2" class="com.nina.spring.bean.Address" parent="address" p:street="xihongmen"></bean>
- bean的作用域
scope="singleton" 默认是单例的,就是每次获得的是同一个bean,容器初始化就创建bean
scope="prototype" 每次向容器获取bean,都会产生一个新的bean,调用时才会创建
- 使用外部属性文件,Spring 提供了一个PropertyPlaceHolderConfigurer的BeanFactory 后置处理器,这个处理器允许用户将Bean配置的部分内容移到属性文件中,可以在Bean配置中使用${var}的变量。Spring还允许属性文件中引进 ${propName},以实现属性间的相互引用。
<!-- 导入配置文件 -->
<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>
- 配置文件中使用Spel,spel类似于el表达式,以#{},来处理。其中可以引用字面变量,可以引用bean(id),引用属性(xx.xx),引用方法。
- bean的生命周期。可以有以下顺序,
构造器
设置属性
init
返回bean
destroy
<bean id="car" class="com.nina.spring.bean.Car" init-method="clone" destroy-method="finalize">
<property name="brand" value="#{'SangTaNa'}"></property>
</bean>
- bean的后置处理器。Spring允许使用bean的后置处理器在调用初始化方法前对bean进行额外处理。需要实现接口BeanPostProcessor, 在xml配置中,只需要配置改bean的class,不需要ID,另外,这种bean 会对所有的bean在init前后进行操作。有必要在方法中进行判断
public class Tree implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
// TODO Auto-generated method stub
return null;
}
public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
// TODO Auto-generated method stub
return null;
}
}
- 通过静态工厂方法来配置bean,按例子,获取的bean是car1,配置的class是工厂的,标注获取的方法,factory-method,如果需要参数,则通过 constructor-arg 配置
<bean id="car1" class="com.nina.spring.factory.SimpleBeanFactory" factory-method="getCar">
<constructor-arg value="aa"></constructor-arg>
</bean>
- 通过实例工厂方法来配置bean,先需要创建工厂本身,再获取bean
- 通过FactoryBean,配置。
- 自定义的FactoryBean 需要实现FactoryBean接口。配置class为factorybean,但是实际返回的是对应的getObject方法对应得实例。
基于注解的方式类配置bean
组件扫描
Spring 能够从classpath下自动扫描和实例化具有特定注解的组件
- @Component 基本注解 标注了一个受Spring 管理的组件
- @Respository标识持久层组件
- @Service 标识业务层或服务层组件
- @Controller 标识表现层组件
- xml中配置 需要导入context命名空间
<context:component-scan base-package="com.nina.spring"></context:component-scan>
- 默认的id为类名的第一个字母小写,如果有特殊要求可以使用value属性,eg.@Service(vallue="ddd"),其实可以写为(“ddd”)
- 可以通过 resour-pattern 指定扫描的资源
- 包含什么需要 use-default-filters属性配合
<context:component-scan base-package="com.nina.spring" use-default-filters="true">
<context:exclude-filter type="annotation" expression=""/>
</context:component-scan>
- 注解建立bean之间的关联关系
- <context:component-scan>元素会自动注册 AutowireAnnotationBeanPostProcessor实例,该实例可以自动装配具有@Autowired,@Resource,@Inject注解的实例
- @Autowired 可以自动装配具有兼容类型的单个Bean属性,可以有一个属性 required=false,就不需要强制要求容器有这个对应的bean了。
- @Autowired 注解的属性名称,如果与bean的id不匹配,可以在bean上指定value,也可以在属性上增加注解 @Qualifier, @Qualifier还可以加到入参上面。
- 另外两个类似
- 泛型依赖注入,Spring 可以为子类注入子类对应的泛型类型的成员变量引用(Spring4.0的新特性哦)
public class User implements Serializable {
private Long id;
private String name;
}
public class BaseService<T> {
@Autowired
protected BaseRepository<T> repository;
public void add(){
System.out.println("service add ...");
System.out.println(repository);
}
}
public class BaseRepository<T> {
}
@Service
public class UserService extends BaseService<User> {
}
@Repository
public class UserRepository extends BaseRepository<User> {
}
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-generic.xml");
UserService service = (UserService) ctx.getBean("userService");
service.add();
}
有关Bean的基础配置注入,暂时先告一段落。