本文基于Spring5.05
官网地址:https://projects.spring.io/sp...java
AnnotationConfigApplicationContext | 一个或多个Java配置类加载Spring应用上下文 |
AnnotationConfigWebApplicationContext | 一个或多个Java配置类加载Spring Web应用上下文 |
ClassPathXmlApplicationContext | 从类路径下的一个或多个XML配置文件加载上下文,把应用上下文的定义文件做为类资源 |
FileSystemXmlApplicationContext | 从文件系统下的一个或多个XML配置文件加载上下文 |
XmlWebApplicationContext | 从Web应用下的一个或多个XML配置文件加载上下文 |
GenericApplicationContext | 以可刷新的方式读取不一样bean定义格式加载上下文 |
实例化 | Spfing对Bean进行实例化 |
填充属性 | Spring将值和bean的引用注入到bean对应的属性中 |
BeanNameAware 的 SetBeanName() | 若是Bean实现了BeanNameAware接口,Spring将bean的id传递给SetBeanNamer()方法 |
BeanFactoryAware 的 setBeanFactory() | 若是Bean实现了BeanFactoryAware,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入 |
ApplicationContextAware 的 setApplicationContext() | 若是Bean实现了ApplicationContextAware,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入 |
BeanPostProcess 的 postProcessBeforeInitialization() | - |
InitializingBean 的 afterPropertiesSet() 和自定义初始方法 | @PostConstruct -> InitializingBean -> init-method |
BeanPostProcess 的 postProcessAfterInitialization() | - |
已完成Bean的初始化,使用Bean直至容器关闭 | - |
DisposableBean 的 destory()方法 和自定义销毁方法 | @PreDestory -> DisposableBean -> destory-method |
1)组件扫描(compoent sacnning):Spring会自动发现应用上下文所建立的bean
2)自动装配(autowiring):Spring自动知足bean之间的依赖
实现自动化配置一般是在Java类中声明注解,并经过组件扫描使指定范围内的注解生效的一种方式正则表达式
元素 | 父元素 | 属性 | 说明 |
<bean> 声明Bean定义 |
<beans> | id | 惟一标示 |
name | 名称,多个用','隔开,不能与已有id重复 | ||
class | 指定实例类型 | ||
scope | 单例/多例 | ||
lazy-init | 懒加载 | ||
autowire | 自动装配策略 | ||
autowire-candidate | 是否参与自动注入 | ||
primary | 优先注入 | ||
depends-on | 依赖指定bean | ||
init-method | 自定义初始化方法 | ||
destroy-method | 自定义销毁方法 | ||
abstract | 抽象类,是则不建立对象 | ||
parent | 指定父类Bean,继承父类属性值 | ||
factory-bean | 指定工厂Bean | ||
factory-method | 指定工厂方法 | ||
<alias> 声明Bean的别名 |
<beans> | name | 指定Bean |
alias | 别名 | ||
<property> 经过Setter方法初始化Bean (可以使用P-命名空间代替) |
<bean> | name | 指定属性名,以setName()形式 |
ref | 给引用类型指定bean | ||
value | 给基本类型赋值 | ||
<constructor-arg> 经过构造器方法初始化Bean (spring3.0后可以使用c-命名空间代替) |
<bean> | index | 构造方法参数索引,从0开始 |
type | 构造方法参数类型,会有歧义 | ||
name | 构造方法参数名称 | ||
ref | 引用类型指定bean | ||
value | 基本类型赋值 | ||
<set>/<List> 声明集合 |
<constructor-arg>/<property> | 注入参数为集合时使用(c/p-命名空间没法装配集合) | |
<ref> 声明集合元素 |
<set>/<List> | bean | 指定Bean定义 |
<value> 声明集合元素 |
<set>/<List> | <value>val</value> | 指定集合字面量元素值 |
util-命名空间 | <beans> | <util:constant> | 应用某个类型的public static域,并将其暴露为bean |
<util:list> | 建立一个java.util.List类型的bean,其中包含值与引用 | ||
<util:set> | 建立一个java.util.Set类型的bean,其中包含值与引用 | ||
<util:map> | 建立一个java.util.Map类型的bean,其中包含值与引用 | ||
<util:properties> | 建立一个java.util.properties类型的bean | ||
<util:property-path> | 应用某个类型的public static域,并将其暴露为bean | ||
<import> | 引入新的xml配置 |
Ps:关于p/c-命名空间,添加xml配置后,在bean中做为属性使用
语法:p:属性名[-ref]="字面量或BeanId"
属性名可设置为 name(参数名)、_0(参数下标,从0开始)、_(只有一个参数时可以使用)spring
注解 | 说明 | 属性 | 属性说明 |
@Bean | 声明Bean定义,定义在方法上,Bean的Id默认为方法名 | value/name | 指定Bean的Id |
autowire | 指定自动注入策略,默认为NO | ||
initMethod | 指定自定义初始化方法 | ||
destroyMethod | 指定自定义销毁方法 | ||
@Scope | 指定做用域 | value/scopeName | 设置单例、多例等做用域 |
proxyMode | 设置动态代理模式,JDK、cglib等 | ||
@Import | 导入新的Java配置类 | value | 指定要导入的Java配置类,可设置单个(a.class)或数组({a.class,b.class}) |
@ImportResource | 导入新的XML配置 | value | 指定导入XML配置路径,可为单个("a.xml")或数组({"a.xml","b.xml"}) |
@PropertySource | 导入新的properties文件 | value | 指定导入properties文件路径,可为单个("a.properties")或数组({"a.properties","b.properties"}) |
注解 | 说明 | 属性 | 属性说明 |
@Configuration | 声明配置类,Spring会从配置类中加载上下文 | value | |
@Component | 声明组件,同@Controller,@Service... | value | 指定Bean的Id,也可经过@Named声明Id(jsr330) |
@Autowired | 可修饰类变量、set方法,以ByType方式自动注入组件,同@Resource(jsr250),@Inject(jsr330) | required | 默认true,未找到注入的Bean会报错,false关闭,关闭时注意NullPointerException |
@Qualifier | 与Autowired配置使用,指定Bean的Id注入 | value | 指定Bean的Id |
@ComponentScan | 启用组件扫描,也可在XML中配置<context:component-scan> | basePackages | 指定扫描包,可接受单个包名("com.*")和数组{"service","controller"},不安全,重构代码修改包结构会出现问题 |
basePackageClasses | 指定类所在的包做为组件扫描的基础包。可经过在须要导入的包中建立并指定Marker interface空接口 |
在Spring3.1中,Spring引入了bean profile的功能,要使用profile,将全部不一样的bean定义整理到一个或多个profile之中,在将应用部署到每一个环境时,要确保对应的profile处于激活(active)的状态。没有指定profile的bean始终会被建立数组
@Profile()
在Spring3.1中,只能在类级别上使用@Profile注释,与@Configuration配合使用
在Spring3.2开始,能够再方法级别上使用,与@Bean注解一同使用安全
在<beans>中声明profile属性
可在<beans>中嵌套声明<beans> 实现多个profile共存一个xml文档session
spring.profiles.active 设置激活的profile
spring.profiles.default active未设置则默认为default值dom
Spring4引入@Conditional注解
可使用到带有@Bean注解的方法上。若是给定的条件为true,就会建立这个Bean,不然忽略。post
@Conditional能够指定任意实现Condition接口的类型,
并实现boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata)返回true则建立Bean测试
检查带有@Bean注解的方法上还有什么其余注解
isAnnotatrd() 指定注解是否存在
getAnnotationAttributes 等获取注解集合ui
spring4开始,Profile注解进行重构,使其基于@conditional和Condition实现。
仅有一个Bean匹配所需的结果时,自动装配才是有效的。
若是不只有一个bean可以匹配结果的话,这种歧义性会阻碍Spring自动装配属性、构造器参数或方法参数。
单例(singleton): 在整个应用中,只会建立bean的一个实例(默认)
原型(prototype):每次注入或经过Spring应用上下文获取的时候,都会建立一个新的bean实例。
会话(session) :在Web应用中,为每一个会话建立一个bean实例
请求(request) :在Web应用中,为每一个请求建立一个bean实例
Java配置:使用 @Scope 注解声明做用域,能够与@Component 或 @Bean一块儿使用
XML配置:<bean scope="singleton">
可经过ConfigurableBeanFactory.SCOPE_PROTOTYPE 或 SCOPE_SINGLETON 指定
也可用WebApplicationContext.SCOPE_SESSION等(须要在Web应用中使用)
@Scope 还有一个proxyMode 能够设置动态代理模式(经过ScopedProxyMode 枚举类来设置JDK、cglib等)
在XML中声明做用域代理:<bean><aop:scoped-proxy ></bean>默认是cglib
可经过设置proxy-target-class=false 更改成JDK代理
1)属性占位符(Property placeholder)
2) Spring表达式语言(SpEL)
最简单方式:声明属性源(@PropertySource导入资源)并经过Spring的Environment来检索属性
@Autowired
Environment env;
String getProperty(String key)
String getProperty(String key, String defaultValue)
T getProperty(String key, Class<T> type)
T getProperty(String key, Class<T> type, String defaultValue)
String getRequiredProperty(String key)
T getRequiredProperty(String key, Class<T> type)
boolean containsProperty(String var1)
Class<T> getPropertyAsClass(String key, Class<T> type)
String[] getActiveProfiles(); 获取激活的profiles
String[] getDefaultProfiles(); 获取默认的profiles
boolean acceptsProfiles(String... var1); 若是environment支持给定profile的话,就返回true
在Spring装配中,占位符的形式为使用"${...}"包装的属性名称
在XML中使用属性占位符(前提是经过<context:property-placeholder location=" "/>引入资源)
<context:property-placeholder location="classpath:demo.properties"/> <bean id="demo" class="" c:_name="${demo.name}">
在Java中使用属性占位符(需配置一个PropertyPlaceholderConfigurer 或 PropertySourcesPlaceholderConfigurer Bean,Spring 3.1 之后推荐后者,由于其可以基于Spring Environment及其属性源来解析占位符)
public class Demo { @Value("${demo.name}") private String name; }
Spring3引入Spring表达式语言(Spring Expression Language,SpEL)。经过表达式,在运行时计算获得值,实现装配。
SpEL的形式为"#{...}"
1) 使用Bean的Id来引用Bean
2)调用方法和访问对象的属性
3)对值进行算术、关系和逻辑运算
4)正则表达式匹配
5)集合操做
除依赖注入,Spring Security支持SpEL定义安全限制规则;Thymeleaf模板支持SpEL引用模型数据
列子:
//获取当前时间的毫秒值,T()表达式会将java.lang.System视为Java中对应的类,并调用其静态方法currentTimeMills() #{T(System).currentTimeMills()} //获取Id为demo的Bean,并引用其name属性(应该是经过get方法获取的吧!未验证) #{demo.name} //经过systemProperties对象引用系统属性 #{systemProperties['disc.title']}
//1)表示字面值 #{3.14159} #{9.87E4} #{'demo'} #{false} //true和false的计算结果就是它们对应的Boolean类型的值 //2)引用bean、属性和方法 #{demo} //获取Id为demo的Bean的引用 #{demo.name} //获取Id为demo的Bean的name属性值 #{demo.getName()} #{demo.getName().toUpperCase()} #{demo.getName()?.toUpperCase()} //避免getName()返回null,出现NullPointException,使用'?.'类型安全的运算符,若是getName()返回null,则不会调用toUpperCase(),表达式返回null //3)在表达式中使用类型(依赖T()这个关键的运算符,其真正价值在于访问目标类型的静态方法和常量) #{T(java.lang.Math)} //表示Math的class对象引用 #{T(java.lang.Math).PI} #{T(java.lang.Math).random()} //4)SpEL运算符 //算数运算:+ - * / % ^ //比较运算:< > == <= >= lt gt eq le ge //逻辑运算:and or not //条件运算:?:(ternary) ?:(Elvis) //正则匹配:matches #{2 * T(java.lang.Math).PI * cricle.radius} #{T(java.lang.Math).PI * cricle.radius ^ 2} //^ 是用于乘方计算的运算符 #{demo.name + 'and' + demo.realname} //使用String类型的值,+ 为链接符 #{demo.age == 20} #{demo.age eq 20} //比较运算符有两种形式:符号形式和文本形式,二者等同,计算结果为Boolean值 #{demo.name != null ? demo.name : "roylion"} //三元运算符的一个常见场景:检查null值,并用一个默认值替代null #{demo.name ?: "roylion"} //此三元运算符一般称为Elvis运算符,用来简化上述场景。 #{demo.emial matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.com'} //匹配正则表达式 //5)计算集合 #{demo.books[4].title} #{demo.books[T(java.lang.Math).random() * demo.books.size()].title} //[] 运算符能够从集合或数组中按照索引获取元素,甚至String(基于0开始) #{'Im a big handsome '[3]} //.?[...] 对集合进行过滤,获得集合的一个子集, //[]中接受另外一个表达式,当SpEL迭代书本列表时,会对每一本书计算这个表达式,若是为true,则会存放到新的集合中 #{demo.books.?[title eq 'springInAction']} #{demo.books.^[title eq 'springInAction']} //.^[] 查询第一个匹配项 #{demo.books.$[title eq 'springInAction']} //.$[] 查询最后一个匹配项 #{demo.books.![title]} //.![] 从集合每一个成员中选择特定的属性放到另一个集合中
保持SpEL表达式的简洁,尽可能不要写复杂的SpEL表达式。由于SpEl表达式是String类型,测试困难