Spring-IOC(2)
scope
<!--Spring使用scope标签来制定bean的作用域(默认为Singleton)-->
<bean id="singletonBean" class="com.fq.instance.SingletonBean" scope="singleton">
</bean>
<bean id="prototypeBean" class="com.fq.instance.PrototypeBean" scope="prototype">
</bean>
Bean生命周期
Spring初始化/销毁bean时, 有时需要作一些处理工作, 因此Spring可以在创建和销毁bean的时候调用bean的两个生命周期方法;
/**
* Created by jifang on 15/12/6.
*/
public class LifecycleBean {
public LifecycleBean() {
System.out.println("Constructor ...");
}
/**
* 声明周期方法需: 无参, 无返回值, 非static
*/
public void setUp() {
System.out.println("SetUp ...");
}
/**
* 同上
*/
public void tearDown() {
System.out.println("TearDown ...");
}
}
配置:
<!-- init-method属性配置初始化方法,destroy-method属性配置销毁方法-->
<bean id="lifecycleBean" class="com.fq.bean.LifecycleBean" init-method="setUp" destroy-method="tearDown">
</bean>
测试
/**
* Created by jifang on 15/12/6.
*/
public class LifecycleBeanTest extends TestCase {
private ClassPathXmlApplicationContext context;
@Before
public void setUp() throws Exception {
context = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
}
@Test
public void testLifecycle(){
LifecycleBean bean = context.getBean("lifecycleBean", LifecycleBean.class);
System.out.println(bean);
}
@After
public void tearDown() throws Exception {
// 必须手动调用context的close方法, 才会执行bean的销毁方法
context.close();
}
}
初始化方法与构造方法的区别?
1) 构造方法为对象申请空间, 完成对象基本属性的初始化;
2) 初始化方法主要完成对象复杂构造过程;
3) Java建议将对象复杂构造过程单独抽取出初始化方法, 如javax.servlet.GenericServlet
的init方法
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
后处理器
Spring提供了BeanPostProcessor接口,在构造Bean对象执行对象初始化(init-method)方法时可以对Bean进行处理;
/**
* Created by jifang on 15/12/6.
*/
public class PrintBeanProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 可以根据beanName来决定对那个Bean进行后处理操作
if (beanName.equals("lifecycleBean")) {
System.out.println("后处理bean -- process before ...");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 如果不制定beanName, 则默认处理所有Bean
System.out.println("后处理bean -- process after ...");
return bean;
}
}
配置
<!-- 为Spring容器所用的bean, 不需配置id -->
<bean class="com.fq.processor.PrintBeanProcessor"></bean>
这样在执行init-method[setUp]的前后, 会分别执行BeanPostProcessor中的两个方法.
后处理器可以在对象构造过程中提供代理,这是AOP自动代理的核心.
XML依赖注入
Spring配置文件支持构造参数属性注入和Setter方法属性注入;
1. 构造参数注入
<bean id="bean" class="com.fq.di.Bean">
<!--
index 代表参数顺序(从0开始)
name 代表参数名
type 参数类型
value 注入的参数值
ref 引用另一个bean元素的id
-->
<constructor-arg index="0" type="java.lang.String" value="fei_qing"></constructor-arg>
<constructor-arg index="1" type="java.lang.Double" value="3.14"></constructor-arg>
</bean>
2. Setter方法注入
<bean id="bean" class="com.fq.di.Bean">
<!--
name 属性名(congSetter方法获得)
value 注入的参数值
ref 引用的另一个bean的id
-->
<property name="name" value="fei_qing"></property>
<property name="price" value="88.8"></property>
</bean>
3. p名称空间注入
P名称空间在spring2.5版本后引入, 目的是为了简化属性依赖注入(setter方法)
<!--
p:属性名="XXX", 引入常量值
p:属性名-ref="XXX", 引用其他Bean对象
-->
<bean id="bean" class="com.fq.di.Bean" p:name="feiqing" p:price="1188">
</bean>
4. SpEL表达式
在spring3.0之后,引入SpEL表达式,以简化属性注入.
#{表达式}, 通过value属性注入: 可以引用一个Bean对象/对象属性/对象方法… 详细可参考Spring 表达式语言(SpEL)
Bean
public class Car {
private String logo;
private double price;
private String owner;
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
}
public class Employ {
private String name;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
配置
<!--SpEL 使用#{}来引用/获取对象-->
<bean id="car" class="com.fq.di.Car">
<property name="logo" value="#{'logo.pic'}"/>
<property name="price" value="#{18.8}"/>
<property name="owner" value="#{'feiqing'}"/>
</bean>
<bean id="employ" class="com.fq.di.Employ">
<!-- 可以直接使用value来引用到对象, 而不是ref -->
<property name="car" value="#{car}"/>
<!-- 可以直接引用一个对象的属性 -->
<!--<property name="name" value="#{car.owner}"/>-->
<!-- 还可以直接调用对象的方法 -->
<property name="name" value="#{car.getOwner().toUpperCase()}"/>
</bean>
4. 集合属性注入
java常见集合: List/Set/Map/Properties等, Spring为每种集合都提供一个标签进行注入;
Bean
public class CollectionBean {
private List<String> list;
private Set<String> set;
private Map<String, String> map;
private Properties properties;
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
配置
<bean id="collectionBean" class="com.fq.di.CollectionBean">
<property name="list">
<list>
<value>aa</value>
<value>bb</value>
<value>cc</value>
<value>dd</value>
</list>
</property>
<property name="set">
<set>
<value>11</value>
<value>12</value>
<value>11</value>
</set>
</property>
<property name="map">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value="value2"/>
</map>
</property>
<property name="properties">
<props>
<prop key="key1">value_1</prop>
<prop key="key2">value_2</prop>
</props>
</property>
</bean>
注解装配
注解配置Bean
在需要Spring管理的类上添加@Component注解
(@Component还可以指定组件名@Component(value = "xxx"))
@Component
public class Bean {
private String name;
private Double price;
public Bean() {
}
public Bean(String name, Double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
引入context命名空间并批量扫描
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.fq.di"/>
</beans>
Spring细化@Component以细分组件功能,提供了以下三个等价注解:
注解 |
说明 |
---|---|
@Controller |
控制器,web层组件 |
@Service |
业务类,业务层组件 |
@Repository |
持久层组件 |
Bean作用域
通过@Scope注解指定作用域
@Component
@Scope("prototype")
public class Bean {
// ...
}
Bean生命周期
销毁
Bean
public class Bean {
@PostConstruct
public void setUp(){
System.out.println("setUp ...");
}
@PreDestroy
public void tearDown(){
System.out.println("tearDown ...");
}
}
注解依赖注入
1. @Value
简单类型
@Component
public class Bean {
@Value("feiqing")
private String name;
@Value("88.88")
private Double price;
// ....
}
复杂属性(使用SpEL表达式)
@Component
public class Bean {
@Value("#{car}")
private Car car;
// ...
}
2. @Autowired
@Autowired 默认按照类型进行注入(如果容器中存在两个相同类型对象,则@Autowired无法注入)
@Component
public class Bean {
@Autowired
private Car car;
// ....
}
@Autowired+@Qualifier指定注入Bean的id
@Component
public class Bean {
@Autowired
@Qualifier("car")
private Car car;
// ...
}
3. @Resource
Spring支持JSR-250规范,可以使用@Resource()进行属性注入,功能和@Autowired相同:
@Controller(value = "bean")
public class Bean {
@Resource(name = "car")
private Car car;
//...
}
注解/XML混合
Bean定义使用XML,Bean关系依赖注入使用注解:
需要在applicationContext.xml中配置:
<context:annotation-config/>
该配置可以使@Resource、@PostConstruct、@PreDestroy、@Autowired注解生效.
如果在配置文件中使用了<context:component-scan base-package="xxx.xx"/>则具有了<context:annotation-config/>的效果, 不必再单独配置.
- 每天一个Linux命令(3)——pwd
- 11-移动端开发教程-zepto.js入门教程
- 【OpenCV学习笔记之一】图像加载,修改及保存
- 【干货】一种直观的方法认识梯度下降
- 漫谈Java IO之普通IO流与BIO服务器
- 浅谈强化学习的方法及学习路线
- 【亲测有效】Win10家庭版Microsoft Edge页面出现乱码的两种解决方案及gpedit.msc命令无法使用的解决策略
- Fiddler抓包7-post请求(json)
- Selenium2+python自动化56-unittest之断言(assert)
- 长文 | 手把手教你如何使用python进行数据分析(最好将文章代码自己码一遍)
- 回归与梯度下降法及实现原理
- 【宅男宅女们的福音】电影天堂最新电影爬取及搜索脚本
- 把模块有关联的放在一个文件夹中 在python2中调用文件夹名会直接失败 在python3中调用会成功,但是调用不能成功的解决方案
- numpy用法小结
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Zookeeper 分布式技术入门
- llvm 对 copy 属性的优化(2)
- 为什么 Linux 默认页大小是 “4KB”?
- Swift Module Interfaces
- Swift 的 MemoryLayout 是如何工作的(1)
- Redis - NoSQL 和 Jedis 入门
- cargo manifest规则使用介绍
- 小程序bindinput和bindblur赋值延迟问题解决
- 小程序监听屏幕滑动事件
- 使用GithubActions发布Vue网站到GithubPage
- 3.QOpenGLWidget-通过着色器来渲染渐变三角形
- 特斯拉大半夜「见鬼」!空无一人的路上,它却看见「幽灵」秒刹车
- .NET 异步详解
- 他被导师半夜敲门叫醒:你得诺贝尔奖了!还曾为5G频谱拍卖设计方案,担任谷歌IPO咨询顾问
- C#实现——十大排序算法之选择排序