文章目录
Spring
IOC
把对象创建和对象之间的调用过程交给Spring进行管理
通过这种方式,可以降低耦合度
1、底层原理:
xml解析、工厂模式、反射
2、实现方法:
1)BeanFactory:
IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用
特点:加载配置文件时候不会创建对象,在使用时才创建对象
2)ApplicationContext:
BeanFactory接口的子接口,一般由开发人员进行使用
特点:加载配置文件时候直接创建对象
使用方法:
ClassPathXmlApplicationContext();
FileSystemXmlApplicationContext();
3、操作
Bean管理
1) 基于XML方式
(一般在实际过程中是通过注解进行配置的,而不是使用配置文件)
① 由Spring创建对象
<bean id="" class=""></bean>
<!--
class的值是你的类的地址文件
id的值就是你对象的唯一标识
创建对象的时候,默认也是执行无参数构造方法完成对象创建,若没有无参构造就会发生错误
-->
② 由Spring注入属性
DI:依赖注入
①set方法注入(通过无参构造方法)
<1> 先在Java文件中创建set方法(略)
<2> 在xml配置文件中进行对象的创建,以及属性的注入
使用property标签创建
<!--set方法注入-->
<!--使用property完成属性注入-->
<bean id="" class =""><!--new对象-->
<!--进行属性的操作-->
<property name = "" value=""></property>
</bean>
<!--有参构造注入-->
②有参构造注入
<1> 先在Java文件中创建有参数的构造方法
public test(int a , int b, String c){
this.a = a;
this.b = b;
this.c = c;
}
<2> 在xml配置文件中进行对象的创建,以及属性的注入
使用constructor-arg标签创建
<bean id ="" class = "">
<constructor-arg name="" value="">
</constructor-arg>
<!--name可以通过index来进行替换,代表参数中的序列号-->
</bean>
2) IOC操作Bean管理
普通bean
工厂bean
创建类,让这个类作为工厂bean,实现接口FactoryBean
实现接口里面的方法,在实现的方法中定义返回的bean类型
定义类型和返回类型可以不一样
自动装配
什么是手动装配,什么是自动装配
通过name,value设置属性的值就是手动装配
根据指定装配规则(属性名称、属性类型),Spring自动将匹配的属性值进行注入就是自动装配
使用
在xml配置文件中对bean标签设置autowire属性,配置自动装配
autowire属性值:
byName:根据属性名称注入。注入值bean的id值和类属性名称一样
byType:根据属性类型注入
外部属性文件
直接配置数据库信息
配置德鲁伊连接池
引入连接依赖的jar包
在xml文件中进行配置对象,包括数据库类型,数据库用户名、密码等
通过外部属性文件配置数据库连接池
创建外部属性文件,properties格式文件,写数据库信息
在里面写入数据库相同的数据库信息
把外部的properties属性文件引入到配置文件中
引入context名称空间
在spring配置文件使用标签引入外部属性文件
配置连接池(根据配置文件中的值进行配置)
3) 基于注解方式实现对象创建(常用)
什么是注解
注解是代码的特殊标记;格式:【@注解名称(属性名称= 属性值,属性名称=属性值。。。。。)】
适用范围
注解可以作用在类、方法、属性上面
注解的目的
简化xml配置
针对Bean管理中创建对象提供注解
@Component
@Service
@Controller
@Repository
上面的四个注解功能是一样的,都可以用来创建bean实例
①引入依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yilGy1ha-1611575664029)(…/AppData/Roaming/Typora/typora-user-images/image-20210116123245535.png)]
②开启组件扫描
<!--扫描多个包时,多个包可以使用逗号
或者
扫描包上层目录-->
<content:component-scan base-package ="包的路径">
</content:component-scan>
③创建类,在类上面添加创建对象注解
//里面的value可以不用写,默认为首字母小写的类,比如First类,那么我默认value="first
@Component(value="值") //类似于<bean id="值" class="路径"></bean>
④注意事项:
Ⅰ怎么在步骤③中扫描时,对目录下的指定的部分进行扫描,而不是对全部进行扫描
<content:component-scan base-package ="包的路径" use-default-filters="false">
<context:include-filter type = "annotation" expression="包下的对应的内容"/>
<!--expression="org.springframework.stereotype.Controller"时,选择包下 含有Controller注解的内容-->
</content:component-scan>
Ⅱ怎么在步骤④扫描时,不扫描目录下指定的部分
<content:component-scan base-package ="包的路径">
<context:include-filter type = "annotation" expression="包下的对应的内容"/>
<!--expression="org.springframework.stereotype.Controller"时,选择包下 不含有Controller注解的内容-->
</content:component-scan>
4)基于注解方式实现属性注入
@AutoWired: 根据属性类型进行自动装配
第一步:把service和dao对象创建,在service和dao类添加创建对象注解
第二步:在service注入dao对象,在service中添加到类型属性,在属性上面使用注解
@Qualifier: 根据属性名称进行注入
使用的原因:因为一个属性类型,也就是一个接口类,可能会有多个实现类,当需要进行准确的注入时,需要再一次通过属性名称进行过滤,也就是上面**@Component、@Service、@Controller、@Repository**标记的value值
和上面的@AutoWired一起使用
在@AutoWired下面添加@Qualifier(value=“值”)来进行准确的注入
@Resource: 可以根据类型注入,也可以根据名称注入
Javax扩展包中的,而不是spring的内容
类型注入时:@Resourse
名称注入时:@Resourse(name=“值”)
@Value: 注入普通类型属性
我理解为常量注入?
@Value(value = "xxx")
private String name;
5)纯注解开发
配置文件爷也不需要,完全注解开发
①创建配置类,替代xml配置文件
@Configuration
@ComponentScan(basePackages={"路径"})
public class 类{
}
②编写测试类
@Test
public void test(){
//采用非纯注解形式开发时,引入xml配置文件的方式
ApplicationContext context = new ClassPathXmlApplicationContext("文件.xml");
//采用纯注解形式开发后,加载配置类的操作
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class) ;
}
4、属性
1)bean的作用域
单实例对象:地址一样,都一样,在创建对象的时候创建
多实例对象:地址不同,值之间是有区别的,在调用getBean的时候才进行创建
默认情况下,创建的bean是单实例对象,但可以人为修改
在xml配置文件bean标签里面有属性用于设置单实例还是多实例
scope
1、singleton 默认值,表示单实例对象
2、prototype 表示多实例对象
2)bean生命周期
从对象创建到销毁的过程
正常情况下5步
①通过构造器创建bean实例(无参数构造)
②为bean的属性设置值和对其他bean引用(调用set方法)
③调用bean初始化方法(需要进行配置初始化方法)
通过在xml中配置bean的属性 : init-method = " name "
④bean可以进行使用
⑤容器关闭时,bean对象销毁(需要进行配置销毁的方法)
也是通过xml中配置bean的属性:destory-method = " name "
还需要配置在测试类中调用实例对象里的 close()
后置处理器,生命周期有7步
①通过构造器创建bean实例(无参数构造)
②为bean的属性设置值和对其他bean引用(调用set方法)
③把bean的实例传递bean后置处理器方法
④调用bean初始化方法(需要进行配置初始化方法)
⑤把bean的实例传递bean后置处理器方法
⑥bean可以进行使用
⑦容器关闭时,bean对象销毁(需要进行配置销毁的方法)
创建后置处理器
创建类,实现接口BeanPostProcessor,并进行重写方法(创建后置处理器)
在xml配置文件中配置上面创建的类,即配置后置处理器
第③步对应重写 postProcessBeforeInitialization
第⑤步对应重写 postProcessAfterInitialization
Aop
面向切面编程(方面)
可以对业务逻辑各个方面进行隔离,从而降低逻辑部分的耦合度,增强开发效率
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过这些分离我们希望它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码
功能:不改变源代码方式添加新的功能
1、底层原理
动态代理的方式进行实现
①有接口情况,使用JDK动态代理
创建接口实现类代理对象,增强类的方法
②没有接口情况,使用CGLIB动态代理
创建当前类子类的代理对象
2、JDK动态代理
使用JDK动态代理,使用Proxy类里面的方法创建代理对象
1)调用newPorxyInstance()方法
方法有三个参数
Ⅰ、类加载项
Ⅱ、将增强方法所在的类,这个类实现的接口,支持多个接口
Ⅲ、实现这个接口InvocationHandler创建代理对象,写增强的部分
2)创建JDK动态代理
①创建接口定义方法
②创建接口实现类,实现方法
③使用Proxy类创建接口代理对象
main(){
Class[] interfaces = {值.class}
testDaoImpl test = new testDaoImpl();
testDao dao = (testDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new testProxy(test))
int result = dao.方法(参数1,参数2);
}
//创建代理对象代码
class testProxy implement InvocationHandler{
//1、创建的是谁的代理对象,就把谁的代理对象传递过来
//2.有参构造传递
//方法1:
//public testProxy (testDaoImpl){
//这里的testDaoImpl就是代理的对象,也就是增强的对象!
//}
//方法2:采用抽象类,这样的话比较灵活
private Object obj;
public testProxy (Object obj){
//这里的testDaoImpl就是代理的对象,也就是增强的对象!
this.obj = obj
}
//3、增强的逻辑
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
//method是执行的方法
//args是传递的参数
//obj就是所要执行的方法
//方法前的动作
//被增强的方法执行
Object res = method.invoke(obj, args);
//方法后的动作
return res;
}
}
3)AOP的术语
①连接点
类里面可以增强的方法就是连接点
②切入点
实际增强的方法就是切入点
③通知(增强)
增强的逻辑部分就是通知(增强)
通知有多种类型
- 前置通知:方法之前的内容
- 后置通知:方法之后的内容
- 环绕通知:方法前面和后面都执行的内容
- 异常通知:异常后的内容
- 最终通知:finally,不论发生什么都会通知
④切面
把通知应用到切入点的过程
也就是向方法中增强方法的过程
3、AOP操作
Spring框架一般都是基于Aspectj实现AOP操作
1)什么是AspectJ
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
2)基于AspectJ实现AOP操作
(需要引入AspectJ相关依赖)
①基于xml配置文件
②基于注解方式(常用)
3)切入点表达式
作用:知道对哪个类里面的哪个方法进行增强
语法结构:execution(【权限修饰符】【返回类型】【类全路径】【方法名称】(【参数列表】))
//举例:对com.test.dao.testDao类里面的test()进行增强
execution(*com.test.dao.testDao.test(a,b));
//举例:对com.test.dao.testDao类里面所有方法进行增强
execution(*com.test.dao.testDao.*(...));
//举例:对com.test.dao包里面所有类里面的所有方法进行增强
execution(*com.test.dao.*.*(...));
公共切入点的提取
若多个目标切面的切入点相同,可以对其进行提取
//相当于把公共方法写到工具类中
@Pointcut(value="execution(*com.test.dao.*.*(...))")
public void pointdemo(){
}
//使用该切入点时,通过方法名称进行使用
@Before(value="pointdemo()")
public void test(){
//do something
}
4)基于xml方式(是由较少,了解即可)
①创建增强类和被增强类
②在xml配置文件创建
③在xml配置文件中配置切入点
<aop:config>
<!--切入点配置,被增强类-->
<aop:pointcut id="" expression="execution(*com.test.dao.*.*(...))"/>
<!--配置切面-->
<aop:aspect ref="增强类">
<!--增强作用在具体方法上-->
<aop:before method="增强方法" pointcut-ref="作用的切入点"/>
</aop:aspect>
</aop:config>
④特殊:完全注解开发
回顾IOC六面的纯注解开发
@Configuration
@ComponentScan(basePackages={"com.test.dao"})
@EnableAspectrJAutoProxy(proxyTargetClass=true)
public class ConfigAop{
}
5)基于注解方式(使用较多)
①创建类,在类里面定义方法
②创建增强类,在里面编写所要增强的动作
在增强类里面,创建方法,让不同方法代表不同通知类型
③进行通知的配置
Ⅰ在spring配置文件中,开启注解扫描(或者在配置类中配置)
Ⅱ使用注解实例化被增强的类,以及增强类的类(在类上面添加**@Component、@Service、@Controller、@Repository**)
Ⅲ在增强类上面添加注解@Aspect
Ⅳ在spring配置文件中开启生成代理对象
<aop:aspectj-autoproxy>
<!--若发现类上面有@Aspect标记,则把这个对象视为代理对象-->
</aop:aspectj-autoproxy>
④配置不同类型的通知
在增强类里面,在作为通知方法(要添加的增强方法)上面添加通知类型注解,并使用切入点表达式配置。
前置通知:@Before(value = “execution(com.test.dao..*(…))”)
后置通知:@AfterReturning(value = “execution(com.test.dao..*(…))”) 有异常不执行
环绕通知:@Around(value = “execution(com.test.dao..*(…))”)
//环绕通知
@Around(value = "execution(*com.test.dao.*.*(...))")
public void test(){
//-------------
//-环绕之前代码-
//-------------
proceedingJoinPoint.proceed();
//-------------
//-环绕之后代码-
//-------------
}
异常通知:@AfterThrowing(value = “execution(com.test.dao..*(…))”)
最终通知:@After(value = “execution(com.test.dao..*(…))”)
⑤增强类的优先级
当多个增强类对同一个方法进行增强,可以设置增强类的优先级
在增强类上面添加注解@Order(数字)(数字代表执行的序列号,数字越小,优先级越高)
JdbcTemplate
JDBC:Java操作数据库的一套规范
JdbcTemplate:spring框架对JDBC进行封装,使用jdbcTemplate方便实现对数据库的操作
1)引入相关依赖jar包
2)连接池的配置
<bean id="dataSourse" class = "" destroy-method="close">
<property name="" value="jdbc:mysql:///"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
3)配置JdbcTemplate对象,注入DataSource
<!--JDBCTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSourse"></property>
</bean>
4)创建service类,创建dao类,在dao注入jdbcTemplate对象
事物操作
1、基本概念
1)什么是事物
事务是数据库操作最基本操作;
逻辑上一组操作,若有一个失败则所有操作都失败
典型场景:转账、付款
2)基本特性
原子性:成功或操作都失败,不存在局部成功
一致性:操作前后总量不变
隔离性:多事务操作时不会产生影响
持久性:发生后产生改变
2、实现方法
1)基本环境搭建
①创建数据库表,添加记录
②创建service,搭建dao,完成对象创建和注入关系
service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource
配置文件中:组件扫描、数据库连接池、JdbcTemplate对象并注入DataSource
③在dao创建方法
④在service中写入行为操作
2)建立事务操作
在操作过程中,若对于像转账操作情况,如果在A转出后B转入前,发生了异常,就会出现A钱少了,但是B的钱没有多的情况。这种情况显然是不合理的。
通过事务可以使得如果操作过程中有一个操作出现错误,那么所有操作就不执行!
①开启事务操作
②进行业务操作
③若没有发生异常,提交事务
④若发生异常,事务回滚
//与下面类似,但是不需要通过try-catch来进行处理
public void test(){
try{
//1、开启事务操作
//2、进行业务操作
//3、若没有发生异常,提交事务
}catch(Exception e){
//4、若发生异常,事务回滚
}
}
3)过程
①事务添加到Service层(业务逻辑层)
②在Spring进行事物管理操作
Ⅰ、编程式事物管理
Ⅱ、声明式事务管理(常用)(底层AOP原理)
基于注解方式(常用)
基于xml配置文件方式
③Spring事物管理API
提供一个接口,代表事物管理器,这个接口针对不同的框架提供了不同的实现类
4)声明式事物操作
①注解方式(常用)
Ⅰ在spring配置文件xml中配置事务管理器
<!--配置事务管理器-->
<bean id="事物管理器" class="org.springframework.jdbc.datasource.DataSourceTransationManager">
<!--注入数据源-->
<property name ="" ref = ""></property>
</bean>
Ⅱ在spring配置文件中,开启事物注解
在spring配置文件中引入名称空间tx
开启事物注解
<tx:annotation-driven transaction-manager="事物管理器"></tx:annotation-driven>
在service类上面(或者里面)添加事务注解
@Transactional
添加到类上面:类里面所有的方法都添加事务
添加到方法上面:只为方法添加事务
②xml配置文件方式
配置事务管理器
配置通知
配置切入点和切面
<!--配置事务管理器-->
<bean id="事物管理器" class="org.springframework.jdbc.datasource.DataSourceTransationManager">
<!--注入数据源-->
<property name ="" ref = ""></property>
</bean>
<!--配置通知-->
<tx:advice id="通知名">
<!--配置事务参数-->
<tx:attributes>
<!--指定哪种规则的方法上面添加事务-->
<tx:method name="方法名" propagation="隔离级别"></tx:method>
</tx:attributes>
</tx:advice>
<!--配置切入点和切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id = "切入点名" expression="execution(表达式见上面内容)"/>
<!--配置切面-->
<aop:devisor advice-ref="通知名" pointcut-ref="切入点名"/>
</aop:config>
③完全注解开发
Ⅰ创建配置类,使用配置类代替xml文件
@Configuration //配置类
@ComponentScan(basePackage="路径")//组件扫描
@EnableTransactionManagement //开启事务
public class test{
//创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName();
dataSourse.setUrl("");
dataSourse.setUsername("");
dataSourse.setPassword("");
return dataSourse;
}
//创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource datasource){
//到ioc容器中根据类型找到datasource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入dataSource
jdbcTemplate.setDataSource(datasource);
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSourse){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSourse);
return transactionManager;
}
}
5)@Transactional参数
//例
@Transaction(propagation = Propagation.REQUIRED , isolation = Isolation.READ UNCOMMITTED, timeout = 30, readOnly=false)
①propagation:事务传播行为
默认是REQUIRED
多事务方法直接进行调用(有事务方法调用无事务方法、有事务方法调用有事务方法、无事务方法调用有事务方法、无事务方法调用无事务方法)这个过程中的事务是如何进行管理的
事务方法:对数据库表数据进行变化的操作
REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行
例如:如果有事务方法调用无事务方法,则无事务方法使用当前有事务方法的事物
如果无事务方法调用其他方法,则创建新事物
REQUIRED_NEW:当前的方法必须启动新事物,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
例如:A方法调用B方法,无论A方法是否有事务,都创建新的事物
SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中
NOT_SUPPORTS:当前的方法不应该运行在事务中,如果有运行的事务,将它挂起
MANDATORY:当前的方法必须运行在事务内部,如果没有正在运行的事务,则抛出异常
NEVER:当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED:如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行
②ioslation:事务隔离级别(见MySQL出现的问题)
事务的隔离性,即多事务操作之间不会产生影响,不考虑隔离性会产生很多问题:脏读、不可重复读、虚读
Ⅰ脏读:一个未提交的事务读取到另一个未提交事务的数据(因为可以回滚,所以数据在提交阶段并不是最终数据)
Ⅱ不可重复读:一个未提交事务读取到另一提交事务修改的数据
Ⅲ虚读:一个未提交事务读取到另一个事务添加的数据
通过设置事务隔离级别,可以解决三个问题
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED(读未题交) | 有 | 有 | 有 |
READ COMITTED(读已提交) | 无 | 有 | 有 |
REPEATABLE READ(可重复读,MySQL默认的隔离级别) | 无 | 无 | 有 |
SERIALIZABLE(串行化) | 无 | 无 | 无 |
③timeout:超时时间
事务需要在一定时间内提交,如果不提交进行回滚
如果不设置默认是-1,表示没有超时时间,单位是秒
⑤readOnly:是否只读
读:查询操作;写:修改操作
readonly默认是false,表示不是只读
⑥RollbackFor:回滚
设置出现哪些异常可以进行事务回滚
⑦noRollbackFor:不回滚
设置出现哪些异常不进行事务的回滚
Spring5新增
要求Java8以上,因为Spring基于Java8
1、整合日志
Spring5自带通用的日志封装,整合了Log4j2,并且是官方建议的东西。
1)引入Log4j2相关的jar包
2)创建Log4j2.xml配置文件
2、支持多个功能
1)支持@Nullable注解
@Nullablle注解可以使用在方法上面、属性上面、参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空
@Nullable
String getId();
//上面操作表示方法返回值可以为空
public void test(@Nullable String beanName......)
//上面操作表示方法参数可以为空
@Nullable
private String test;
//上面操作表示属性值可以为空
2)支持函数式风格GenericApplicationContext
创建GenericApplicationContext对象
调用context的方法对象进行注册
3、支持整合JUnit5
JUnit:单元测试框架
1)JUnit4
①引入Spring相关针对测试依赖jar包
②创建测试类,使用注解方式完成
@RunWith(SpringJUnit4ClassRunner.class)//指定单元测试的版本
@ContextConfiguration(".....xml")//加载配置文件
public class testJUnit4{
//注入service
//使用方法
}
2)JUnit5
①引入JUnit5的相关依赖包
②创建测试类,使用注解方式完成
@ExtendWith(SpringExtension.class)//指定单元测试的版本
@ContextConfiguration(".....xml")//加载配置文件
public class testJUnit4{
//注入service
//使用方法
}
3)复合注解完成注解整合
@SpringJUnitConfig(locations=".....xml")
public class testJUnit4{
//注入service
//使用方法
}
4、Webflux
1)
2)
3)
4)
要点概况
1、属性值包含特殊符号 或 属性值是空值
<property name="">
<!--特殊符号-->
<value>
<!--"<<内容是这里>>""-->
<![CDATA[<<内容是这里>>]]>
</value>
</property>
<property name="">
<!--空值-->
<null/>
</property>
基本包:beans、context、core、expression
数据操作:JDBC
日志包:common-loggiong
对象的配置
t4
①引入Spring相关针对测试依赖jar包
②创建测试类,使用注解方式完成
@RunWith(SpringJUnit4ClassRunner.class)//指定单元测试的版本
@ContextConfiguration(".....xml")//加载配置文件
public class testJUnit4{
//注入service
//使用方法
}
2)JUnit5
①引入JUnit5的相关依赖包
②创建测试类,使用注解方式完成
@ExtendWith(SpringExtension.class)//指定单元测试的版本
@ContextConfiguration(".....xml")//加载配置文件
public class testJUnit4{
//注入service
//使用方法
}
3)复合注解完成注解整合
@SpringJUnitConfig(locations=".....xml")
public class testJUnit4{
//注入service
//使用方法
}
4、Webflux
1)
2)
3)
4)
要点概况
1、属性值包含特殊符号 或 属性值是空值
<property name="">
<!--特殊符号-->
<value>
<!--"<<内容是这里>>""-->
<![CDATA[<<内容是这里>>]]>
</value>
</property>
<property name="">
<!--空值-->
<null/>
</property>
基本包:beans、context、core、expression
数据操作:JDBC
日志包:common-loggiong
对象的配置