博客
关于我
spring(SpEL、 IOC 容器中 Bean 的生命周期方法、配置bean(多种方法))
阅读量:483 次
发布时间:2019-03-06

本文共 11496 字,大约阅读时间需要 38 分钟。

Spring表达式语言:SpEL

Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。

语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL
SpEL 为 bean 的属性进行动态赋值提供了便利
通过 SpEL 可以实现:
通过 bean 的 id 对 bean 进行引用
调用方法以及引用对象中的属性
计算表达式的值
正则表达式的匹配

Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。

语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL

SpEL 为 bean 的属性进行动态赋值提供了便利
通过 SpEL 可以实现:
通过 bean 的 id 对 bean 进行引用
调用方法以及引用对象中的属性
计算表达式的值
正则表达式的匹配

SpEL:字面量

字面量的表示:

整数:< property name=“count” value="#{5}"/>
小数:< property name=“frequency” value="#{89.7}"/>
科学计数法:< property name=“capacity” value="#{1e4}"/>
String可以使用单引号或者双引号作为字符串的定界符号:< property name=“name” value="#{‘Chuck’}"/> 或 < property name=‘name’ value=’#{“Chuck”}’/>
Boolean:< property name=“enabled” value="#{false}"/>

SpEL:引用 Bean、属性和方法(1)

引用其他对象:在这里插入图片描述

引用其他对象的属性
在这里插入图片描述

调用其他方法,还可以链式操作在这里插入图片描述在这里插入图片描述

SpEL支持的运算符号(1)

算数运算符:+, -, *, /, %, ^:

在这里插入图片描述
加号还可以用作字符串连接:
在这里插入图片描述
比较运算符: <, >, ==, <=, >=, lt, gt, eq, le, ge
在这里插入图片描述
逻辑运算符号: and, or, not, |
在这里插入图片描述
if-else 运算符:?: (ternary), ?: (Elvis)
在这里插入图片描述
if-else 的变体
在这里插入图片描述
正则表达式:matches
在这里插入图片描述

SpEL:引用 Bean、属性和方法(2)

调用静态方法或静态属性:通过 T() 调用一个类的静态方法,它将返回一个 Class Object,然后再调用相应的方法或属性:

在这里插入图片描述
例子:

//bean Carpackage wo;public class Car {   	private String brand;	private int maxSpeed;	private double price;	public String getBrand() {   		return brand;	}	public void setBrand(String brand) {   		this.brand = brand;	}	public int getMaxSpeed() {   		return maxSpeed;	}	public void setMaxSpeed(int maxSpeed) {   		this.maxSpeed = maxSpeed;	}	public double getPrice() {   		return price;	}	public void setPrice(double price) {   		this.price = price;	}	public Car(String brand, int maxSpeed, double price) {   		super();		this.brand = brand;		this.maxSpeed = maxSpeed;		this.price = price;	}	@Override	public String toString() {   		return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + ", price="				+ price + "]";	}	public Car() {   		super();		// TODO Auto-generated constructor stub	}}///bean Personpackage wo;import java.util.List;public class Person {   private String name;private Car car;@Overridepublic String toString() {   	return "Person [car=" + car + ", name=" + name + "]";}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;}}/.//全局配置文件/spring1/src/beans-spel.xml
//测试package wo;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main { public static void main(String[] args) { //1. 创建 Spring 的 IOC 容器ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-spel.xml");System.out.println(ctx.getBean("person")); }}

IOC 容器中 Bean 的生命周期方法

Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务.

Spring IOC 容器对 Bean 的生命周期进行管理的过程:
通过构造器或工厂方法创建 Bean 实例
为 Bean 的属性设置值和对其他 Bean 的引用
调用 Bean 的初始化方法
Bean 可以使用了
当容器关闭时, 调用 Bean 的销毁方法
在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
例子(在上面基础上):

//bean car 改动	public Car() {   		super();		// TODO Auto-generated constructor stub		System.out.println("car' constructor");	}public void init(){   	System.out.println("car' init");	}public void destroy(){   	System.out.println("car' destroy");	}		public void setPrice(double price) {   		System.out.println("price");			this.price = price;	}///全局配置文件/spring1/src/beans-spel.xml
//测试ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-spel.xml");System.out.println(ctx.getBean("car"));ctx.close();

创建 Bean 后置处理器

Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.

Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.
对Bean 后置处理器而言, 需要实现 在这里插入图片描述 接口. 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的以下两个方法:
在这里插入图片描述
添加 Bean 后置处理器后 Bean 的生命周期
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
通过构造器或工厂方法创建 Bean 实例
为 Bean 的属性设置值和对其他 Bean 的引用
将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法
调用 Bean 的初始化方法
将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization方法
Bean 可以使用了
当容器关闭时, 调用 Bean 的销毁方法
例子(在上面基础上):

// 后置处理器package wo;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class Bean implements BeanPostProcessor {   	@Override	public Object postProcessAfterInitialization(Object arg0, String arg1)			throws BeansException {   		// TODO Auto-generated method stubs		System.out.println("before");		return arg0;	}	@Override	public Object postProcessBeforeInitialization(Object arg0, String arg1)			throws BeansException {   		// TODO Auto-generated method stub		System.out.println("after");		return arg0;	}}///全局配置文件/spring1/src/beans-spel.xml

配置bean

通过调用静态工厂方法创建 Bean

调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节.要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 < constrctor-arg> 元素为该方法传递方法参数.

例子(在上面基础上):

//静态工厂package wo;import java.util.HashMap;import java.util.Map;//*静态工厂方法:直接调用某一个类的静态方法就可以返回Bean的实例public class StaticFactory {   static Map
a=new HashMap
();static{ a.put("I", new Car("I",26,32));}//静态工厂方发public static Car getCar(String l){ return a.get(l);}}全局配置文件/spring1/src/beans-spel.xml

通过调用实例工厂方法创建 Bean

实例工厂方法: 将对象的创建过程封装到另外一个对象实例的方法里. 当客户端需要请求对象时, 只需要简单的调用该实例方法而不需要关心对象的创建细节.

要声明通过实例工厂方法创建的 Bean
在 bean 的 factory-bean 属性里指定拥有该工厂方法的 Bean
在 factory-method 属性里指定该工厂方法的名称
使用 construtor-arg 元素为工厂方法传递方法参数
例子(在上面基础上):

//工厂方法package wo;import java.util.HashMap;import java.util.Map;//实例工厂方法:实例工厂的方法。即现需要创建工厂本身,再调用工厂的实例方法来返回bean的属性public class Instance {   	private Map
a=new HashMap
(); public Instance(){ a.put("I", new Car("I",26,32)); } public Car getCar(String l) { return a.get(l);}}////全局配置文件/spring1/src/beans-spel.xml
///System.out.println(ctx.getBean("car2"));

实现 FactoryBean 接口在 Spring IOC 容器中配置 Bean

Spring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, 即FactoryBean.

工厂 Bean 跟普通Bean不同, 其返回的对象不是指定类的一个实例, 其返回的是该工厂 Bean 的 getObject 方法所返回的对象
在这里插入图片描述
例子(在上面基础上):

//FactoryBeanpackage wo;import org.springframework.beans.factory.FactoryBean;public class CarBean implements FactoryBean
{ private String brand; public void setBrand(String brand) { this.brand = brand;} @Override public Car getObject() throws Exception { // TODO Auto-generated method stub return new Car(brand,26,38.5); } @Override public Class
getObjectType() { // TODO Auto-generated method stub return Car.class; } @Override public boolean isSingleton() { // TODO Auto-generated method stub return true; }}////全局配置文件/spring1/src/beans-spel.xml

(通过注解配置)在 classpath 中扫描组件

组件扫描(component scanning): Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件.

特定组件包括:
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称
例子:

//各个bean//1.package ta;import org.springframework.stereotype.Component;@Componentpublic class TestObject {   }//2.package ta.controller;import org.springframework.stereotype.Controller;@Controllerpublic class UserController {   public void execute(){   	System.out.println("controller");}}//3.package ta.service;import org.springframework.stereotype.Service;@Servicepublic class UserService {   public void add(){   	System.out.println("add");}}//4.package ta.you;public interface UserRepository {   public void save();}package ta.you;import org.springframework.stereotype.Repository;@Repository("userRepository")public class UserAction implements UserRepository {   	@Override	public void save() {   		// TODO Auto-generated method stubSystem.out.println("save");	}}//全局配置文件/spring1/src/beans-annotation.xml
////测试package ta;import org.springframework.context.support.ClassPathXmlApplicationContext;import ta.controller.UserController;public class Main { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml"); System.out.println(ctx.getBean("testObject")); System.out.println(ctx.getBean("userRepository")); ((UserController) ctx.getBean("userController")).execute(); ctx.close(); }}

当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明 < context:component-scan> :

base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.
当需要扫描多个包时, 可以使用逗号分隔.
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern(base-package的子包) 属性过滤特定的类,示例(在上面的基础上):

全局配置文件/spring1/src/beans-annotation.xml

< context:include-filter> 子节点表示要包含的目标类

< context:exclude-filter> 子节点表示要排除在外的目标类
< context:component-scan> 下可以拥有若干个 < context:include-filter> 和 < context:exclude-filter> 子节点
< context:include-filter> 和 < context:exclude-filter> 子节点支持多种类型的过滤表达式:
在这里插入图片描述
示例(在上面的基础上):

全局配置文件/spring1/src/beans-annotation.xml//1.
//2.
//3
//4.

组件装配

context:component-scan 元素还会自动注册 AutowiredAnnotationBeanPostProcessor 实例, 该实例可以自动装配具有 @Autowired 和 @Resource 、@Inject注解的属性

使用 @Autowired 自动装配 Bean

@Autowired 注解自动装配具有兼容类型的单个 Bean属性

构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
例子(在之前例子基础上):

全局配置文件/spring1/src/beans-annotation.xml
/////修改bean //1. import ta.service.UserService;@Controllerpublic class UserController { @Autowired//也可放到对应的set方法中 当不被设置时 //@Autowired(required=false) private UserService a; public void execute(){ System.out.println("controller"); a.add();}}//2.import ta.you.UserRepository;@Servicepublic class UserService { @Autowired private UserRepository ab;public void add(){ System.out.println("add"); ab.save();}}/////测试((UserController) ctx.getBean("userController")).execute();

默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作.(1.属性名和注解名一致)

@Servicepublic class UserService {   	@Autowired(required=false)	private UserRepository userRepository;public void add(){   	System.out.println("add");	userRepository.save();}}@Repository("userRepository")public class UserAction implements UserRepository {   	@Override	public void save() {   		// TODO Auto-generated method stubSystem.out.println("save");	}}

此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注@Qualifier 已指定注入 Bean 的名称

例子:(在前面的基础上)

//修改bean/spring1/src/ta/service/UserService.javapublic class UserService {   	@Autowired	@Qualifier("userRepository")	private UserRepository ab;public void add(){   	System.out.println("add");	ab.save();}}//2./spring1/src/ta/you/UserAction.java@Repository("userRepository")public class UserAction implements UserRepository {   	@Override	public void save() {   		// TODO Auto-generated method stubSystem.out.println("save");	}}

@Autowired

@Qualifier(“userRepository”)
也可都在在对应的set方法前或者@Autowired在set前,(public void setxx(@Qualifier(“userRepository”)A a))
@Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
@Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
@Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值

使用 @Resource 或 @Inject 自动装配 Bean

Spring 还支持 @Resource 和 @Inject 注解,这两个注解和 @Autowired 注解的功用类似

@Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为 Bean 的名称
@Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性
建议使用 @Autowired 注解

泛型依赖注入

Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用
在这里插入图片描述

整合多个配置文件

Spring 允许通过 将多个配置文件引入到一个文件中,进行配置文件的集成。这样在启动 Spring 容器时,仅需要指定这个合并好的配置文件就可以。

import 元素的 resource 属性支持 Spring 的标准的路径资源
在这里插入图片描述

转载地址:http://aevdz.baihongyu.com/

你可能感兴趣的文章
MTCNN 人脸检测
查看>>
MyEcplise中SpringBoot怎样定制启动banner?
查看>>
MyPython
查看>>
MTD技术介绍
查看>>
MySQL
查看>>
MySQL
查看>>
mysql
查看>>
MTK Android 如何获取系统权限
查看>>
MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
查看>>
MySQL - ERROR 1406
查看>>
mysql - 视图
查看>>
MySQL - 解读MySQL事务与锁机制
查看>>
MTTR、MTBF、MTTF的大白话理解
查看>>
mt_rand
查看>>
mysql -存储过程
查看>>
mysql /*! 50100 ... */ 条件编译
查看>>
mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
查看>>
mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
查看>>
mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
查看>>
mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
查看>>