怎么创建网站相册,现在什么app引流效果好,前端培训费用大概多少郑州,ui设计是学什么的Spring学习笔记——1 一、Spring入门1.1、学习路线1.2、传统Javaweb开发困惑及解决方法1.3、三种思想的提出和框架概念1.3.1、IoC、DI和AOP思想提出1.3.2、框架的基本特点 1.4、Spring概述1.5、BeanFactory快速入门1.6、ApplicationContext快速入门1.7、BeanFactory与Applicati… Spring学习笔记——1 一、Spring入门1.1、学习路线1.2、传统Javaweb开发困惑及解决方法1.3、三种思想的提出和框架概念1.3.1、IoC、DI和AOP思想提出1.3.2、框架的基本特点 1.4、Spring概述1.5、BeanFactory快速入门1.6、ApplicationContext快速入门1.7、BeanFactory与ApplicationContext的关系1.8、BeanFactory和ApplicationContext的继承体系 二、基于XML方式Bean应用2.1、Bean的配置概述2.2、beanName和别名配置2.3、Bean的作用范围scope配置2.4、Bean的延迟加载2.5、Bean的初始化方法和销毁方法2.6、InitializingBean方式2.7、实例化Bean的方式-构造方法方式2.7.1、静态工厂方法方式2.7.2、实例工厂方法方式2.7.3、有参数的静态工厂和实例工厂方法2.7.4、实现FactoryBean规范延迟实例化Bean 2.8、注入2.8.1、注入方式和注入数据类型2.8.2、自动装配 2.9、命名空间的种类2.9.1、beans的profile属性切换环境2.9.2、import标签2.9.3、alias标签2.9.1、自定义命名空间的使用步骤 三、Spring常用的三种getBean的API四、Spring配置非自定义Bean4.1、DruidDatasource4.2、Connection4.3、Date4.4、SqlSessionFactory 五、Bean实例化的基本流程5.1、BeanDefinition5.2、单例池和流程总结 六、Spring的Bean工厂后处理器6.1、入门6.2、注册BeanDefinition6.3、BeanDefinitionRegistryPostProcessor6.4、完善实例化流程图6.5、自定义Component 七、Spring的Bean后处理器7.1、概念和入门7.2、before和after方法的执行时机7.3、案例-日志功能增强7.4、再次完善实例化基本流程图 八、SpringBean的生命周期8.1、概述8.2、初始化阶段执行步骤8.3、初始化阶段注入属性信息封装8.4、属性注入的三种情况8.5、单向对象注入的代码验证8.6、循环依赖概念及解决方案8.7、三级缓存的设计原理8.8、循环依赖源码流程剖析8.9、Aware接口 九、Spring IoC容器实例化Bean整体流程图十、Spring xml方式整和第三方框架10.1、Mybatis整合Spring实现10.2、Mybatis整合Spring源码解析10.3、加载外部properties文件10.4、自定义空间步骤10.5、自定义命名空间案例 一、Spring入门
1.1、学习路线 1.2、传统Javaweb开发困惑及解决方法
问题一:层与层之间紧密耦合在了一起接口与具体实现紧密耦合在了一起
解决思路:程序代码中不要手动new对象第三方根据要求为程序提供需要的Bean对象 问题二:通用的事务功能耦合在业务代码中通用的日志功能耦合在业务代码中
解决思路:程序代码中不要手动new对象第三方根据要求为程序提供需要的Bean对象的代理对象
1.3、三种思想的提出和框架概念
1.3.1、IoC、DI和AOP思想提出 IoC思想 lnversion of Control控制反转,强调的是原来在程序中创建Bean的权利反转给第三方。 DI思想 Dependency Injection依赖注入强调的Bean之间关系这种关系第三方负责去设置。 AOP思想 Aspect Oriented Programming面向切面编程,功能的横向抽取主要的实现方式就是Proxy 1.3.2、框架的基本特点
框架(Framework)是基于基础技术之上从众多业务中抽取出的通用解决方案;框架是一个半成品使用框架规定的语法开发可以提高开发效率可以用简单的代码就能完成复杂的基础业务;框架内部使用大量的设计模式、算法、底层代码操作技术如反射、内省、xml解析、注解解析等;框架一般都具备扩展性;有了框架我们可以将精力尽可能的投入在纯业务开发上而不用去费心技术实现以及一些辅助业务。
Java中常用的框架:
不同语言不同领域都有属于自己的框架使用框架开发是作为程序员的最基础的底线。Java语言中的框架可以分为基础框架和服务框架:
基础框架:完成基本业务操作的框架如MyBatis、Spring、SpringMVC、Struts2、Hibernate等服务框架:特定领域的框架一般还可以对外提供服务框架如MQ、ES、Nacos等
1.4、Spring概述
spring是一个开源的轻量级Java开发应用框架可以简化企业级应用开发。Spring解决了开发者在JavaEE开发中遇到的许多常见的问题提供了功能强大IOC、AOP及Web MVC等功能。是当前企业中Java开发几乎不能缺少的框架之一。Spring的生态及其完善不管是Spring哪个领域的解决方案都是依附于在Spring Framework基础框架的。
Spring框架的历史
Jsp 默默扛下所有;MVC三层架构分工明确但开发成本及其高;EJB重量级框架出现走出一个困境有进入另一个困境;Spring春天来到随之SSH风生水起、称霸武林;Spring 稳住江湖大哥位置SSM开始上位;、Spring本着“拿来主义”的思维快速发展生态不断健全;SpringBoot 又一里程碑崛起把“约定大于配置“思想玩儿的炉火纯青;SpringCloud打包了微服务众多解决方案应对互联网项目更加easy!
Spring Framework技术栈图示 1.5、BeanFactory快速入门
通过BeanFactory完成IoC思想的实现
导入Spring的jar包或Maven坐标;
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.7/version
/dependency定义UserService接口及其UserServicelmpl实现类;
public interface UserService {
}public class UserServiceImpl implements UserService {
}创建beans.xml配置文件将UserServicelmpl的信息配置到该xml中;
bean iduserService classcom. itheima.service.impl.UserServiceImpl/bean编写测试代码创建BeanFactory加载配置文件获取UserService实例对象。
//创建工厂对象
DefaultListableBeanFactory BeanFactory new DefaultListableBeanFactory();
//创建一个读取器XML文件
XmlBeanDefinitionReader Reader new XmlBeanDefinitionReader(BeanFactory);
//读取配置文件给工厂
Reader.loadBeanDefinitions(beans.xml);
//根据id获取Bean实例对象
UserService userService (UserService)BeanFactory.getBean(UserService);实现DI依赖注入
定义UserDao接口及其UserDaolmpl实现类;修改UserServicelmpl代码添加一个setUserDao(UserDao userDao)用于接收注入的对象;
public class UserServiceImpl implements UserService {public void setUserDao(UserDao userDao){System.out.println(BeanFactory调用方法获取userDao设置到此处userDao);}
}修改beans.xml配置文件在UserDaolmpl的bean中嵌入property配置注入;
bean idUserService classcom.Smulll.service.Impl.UserServiceImplproperty nameuserDao refUserDao/
/bean
bean idUserDao classcom.Smulll.Dao.Impl.UserDaoImpl/bean修改测试代码获得UserService时setUserService方法执行了注入操作。
//创建工厂对象
DefaultListableBeanFactory BeanFactory new DefaultListableBeanFactory();
//创建一个读取器XML文件
XmlBeanDefinitionReader Reader new XmlBeanDefinitionReader(BeanFactory);
//读取配置文件给工厂
Reader.loadBeanDefinitions(beans.xml);
//根据id获取Bean实例对象
UserService userService (UserService)BeanFactory.getBean(UserService);1.6、ApplicationContext快速入门
ApplicationContext 称为Spring容器内部封装了BeanFactory比BeanFactory功能更丰富更强大使用ApplicationContext进行开发时xml配置文件的名称习惯写成applicationContext.xml
//创建ApplicationContext加载配置文件实例化容器
ApplicationContext applicationContext new ClassPathxmlApplicationContext(applicationContext.xml);
//根据beanName获得容器中的Bean实例
UserService userService (UserService) applicationContext.getBean(UserService);
System.out.println(userService) ;1.7、BeanFactory与ApplicationContext的关系
BeanFactory是Spring的早期接口称为Spring的Bean工厂 ApplicationContext是后期更高级接口称之为Spring容器;ApplicationContext在BeanFactory基础上对功能进行了扩展例如:监听功能、国际化功能等。 BeanFactory的API更偏向底层ApplicationContext的API大多数是对这些底层API的封装;Bean创建的主要逻辑和功能都被封装在BeanFactory中ApplicationContext不仅继承了BeanFactory而且ApplicationContext内部还维护着BeanFactory的引用所以,ApplicationContext与BeanFactory既有继承关系又有融合关系。Bean的初始化时机不同原始BeanFactory是在首次调用getBean时才进行Bean的创建 ApplicationContext则是配置文件加载容器一创建就将Bean都实例化并初始化好。
ApplicationContext除了继承了BeanFactory外还继承了ApplicationEventPublisher(事件发布器)、ResouresPatternResolver(资源解析器)、MessageSource(消息资源等。但是ApplicationContext的核心功能还是BeanFactory。
1.8、BeanFactory和ApplicationContext的继承体系
BeanFactory的继承体系
BeanFactory是核心接口项目运行过程中肯定有具体实现参与这个具体实现就是DefaultListableBeanFactory而ApplicationContext内部维护的Beanfactory的实现类也是它 ApplicationContext的继承体系
只在Spring基础环境下即只导入spring-context坐标时此时ApplicationContext的继承体系
只在Spring基础环境下常用的三个ApplicationContext作用如下
实现类功能描述ClassPathXmlApplicationContext加载类路径下的xml配置的ApplicationContextFileSystemXmlApplicationContext加载磁盘路径下的xml配置的ApplicationContextAnnotationConfigApplicationContext加载注解配置类的ApplicationContext
如果Spring基础环境中加入了其他组件解决方案如web层解决方案即导入spring-web坐标此时ApplicationContext的继承体系
dependencygroupIdorg.springframework/groupIdartifactIdspring-web/artifactIdversion5.3.7/version
/dependency只在Spring的Web环境下常用的两个ApplicationContext作用如下
实现类功能描述XmlWebApplicationContextweb环境下加载类路径下的xml配置的ApplicationContextAnnotationConfigWebApplicationContextweb环境下加载磁盘路径下的xml配置的ApplicationContext
二、基于XML方式Bean应用
2.1、Bean的配置概述
Spring开发中主要是对Bean的配置Bean的常用配置:
Xml配置方式功能描述bean id“” class“”Bean的id和全限定名配置bean name“”通过name设置Bean的别名通过别名也能直接获取到Bean实例bean scope“”Bean的作用范围 BeanFactory作为容器时取值singleton和prototypebean lazy-init“”Bean的实例化时机是否延迟加载。BeanFactory作为容器时无效bean init-method“”Bean实例化后自动执行的初始化方法method指定方法名bean destroy-method“”Bean实例销毁前的方法method指定方法名bean autowire“byType”设置自动注入模式常用的有按照类型byType按照名字byNamebean factory-bean“” factory-method“”/指定哪个工厂Bean的哪个方法完成Bean的创建
2.2、beanName和别名配置
Bean的基础配置
例如:配置UserDaolmpl由Spring容器负责管理
bean iduserDao classcom.itheima.dao .impl.UserDaoImp! /此时存储到Spring容器(singleObjects单例池)中的Bean的beanName是userDao值是UserDaolmpl对象可以根据beanName获取Bean实例
applicationContext.getBean(userDao);如果不配置id则Spring会把当前Bean实例的全限定名作为beanName
applicationContext.getBean(com.itheima.dao.impl.UserDaoImpl);Bean的别名配置
可以为当前Bean指定多个别名根据别名也可以获得Bean对象
bean iduserDao nameaaa,bbb classcom.itheima.dao.impl.UserDaoImp1 /此时多个名称都可以获得UserDaolmpl实例对象
applicationContext.getBean(userDao);
applicationContext.getBean(aaa);
applicationContext.getBean(bbb);2.3、Bean的作用范围scope配置
默认情况下单纯的Spring环境Bean的作用范围有两个: Singleton和Prototype
singleton:单例默认值Spring容器创建的时候就会进行Bean的实例化并存储到容器内部的单例池中每次getBean时都是从单例池中获取相同的Bean实例;prototype:原型Spring容器初始化时不会创建Bean实例当调用getBean时才会实例化Bean每次getBean都会创建一个新的Bean实例。
2.4、Bean的延迟加载
当lazy-init设置为true时为延迟加载也就是当Spring容器创建的时候不会立即创建Bean实例等待用到时在创建Bean实例并存储到单例池中去后续在使用该Bean直接从单例池获取即可本质上该Bean还是单例的
bean iduserDao class com.itheima.dao.impl.UserDaoImpl lazy-inittrue/2.5、Bean的初始化方法和销毁方法
Bean在被实例化后可以执行指定的初始化方法完成一些初始化的操作Bean在销毁之前也可以执行指定的销毁方法完成一些操作初始化方法名称和销毁方法名称通过
bean iduserDao class com.itheima.dao .impl.UserDaoImpl init-methodinit destroy-methoddestroy /public class UserDaoImpl implements UserDao {public UserDaoImpl() { System.out.println(UserDaoImpl创建了...);}public void init(){ System.out.println(初始化方法...);}public void destroy(){ system.out.println(销毁方法...);}
}2.6、InitializingBean方式
扩展除此之外我们还可以通过实现InitializingBean接口完成一些Bean的初始化操作如下:
public class UserDaoImpl implements UserDao,InitializingBean {public UserDaoImpl(){System.out.println(UserDaoImpl创建了...);}public void init(){System.out.println(初始化方法...);}public void destroy(){System.out.println(销毁方法...);}//执行时机早于init-method配置的方法public void afterPropertiesSet() throws Exception {System.out.println(InitializingBean...);}
}2.7、实例化Bean的方式-构造方法方式
Bean的实例化配置
Spring的实例化方式主要如下两种:
构造方式实例化: 底层通过构造方法对Bean进行实例化工厂方式实例化: 底层通过调用自定义的工厂方法对Bean进行实例化
构造方式实例化Bean又分为无参构造方法实例化和有参构造方法实例化Spring中配置的bean几乎都是无参构造该方式此处不在赘述。下面讲解有参构造方法实例化Bean
//有参构造方法
public UserDaoImpl (String name) {}有参构造在实例化Bean时需要参数的注入通过constructor-arg标签嵌入在bean标签内部提供构造参数如下:
bean iduserDao classcom.itheima.dao .impl.UserDaoImplconstructor-arg namename valuehaohao /
/bean2.7.1、静态工厂方法方式
工厂方式实例化Bean又分为如下三种:
静态工厂方法实例化Bean实例工厂方法实例化Bean实现FactoryBean规范延迟实例化Bean
使用该静态工厂方法的优点
可以执行一些创建对象之前其他的逻辑操作可以生成一些其他工具类或jar包使用静态方法创造的对象
public class FactoryDemo1 {public static UserService CreateUserService(){return new UserServiceImpl();}
}bean idFactoryDemo1 classcom.Smulll.Factory.FactoryDemo1 factory-methodCreateUserService/bean2.7.2、实例工厂方法方式
使用该工厂方法的优点
可以执行一些创建对象之前其他的逻辑操作可以生成一些其他工具类或jar包通过方法来创造的对象
package com.Smulll.Factory;import com.Smulll.service.Impl.UserServiceImpl;
import com.Smulll.service.UserService;public class FactoryDemo2 {public UserService CreateUserService(){return new UserServiceImpl();}
}!--配置实例工厂方法--
!--先设置工厂对象--
bean idfactoryDemo2 classcom.Smulll.Factory.FactoryDemo2/bean
!--在设置工厂方法--
bean idfactoryUser factory-beanfactoryDemo2 factory-methodCreateUserService/bean2.7.3、有参数的静态工厂和实例工厂方法
bean idfactoryUser factory-beanfactoryDemo2 factory-methodCreateUserServiceconstructor-arg namename valuezhangsan/
/bean该参数是工厂方法构造Bean方法的参数
2.7.4、实现FactoryBean规范延迟实例化Bean
使工厂类继承FactoryBeanUserDao 通过getObject()方法返回对象
public class FactoryDemo3 implements FactoryBeanUserDao {Overridepublic UserDao getObject() throws Exception {return new UserDaoImpl();}Overridepublic Class? getObjectType() {return null;}
}bean idfactoryDemo3 classcom.Smulll.Factory.FactoryDemo3/bean该方法有延迟功能只有调用类时才会将getObject()方法返回的类储存到FactoryBean缓存当中
2.8、注入
2.8.1、注入方式和注入数据类型
Bean的依赖注入又两种方式
注入方式配置方式通过Bean的set方法注入property nameuserDao refuserDao /property nameuserDao valuehaohao/通过构造Bean的方法进行注入constructor-arg namename refuserDao/constructor-arg namename valuehaohao/
其中ref是reference的缩写形式翻译为:涉及参考的意思用于引用其他Bean的id。value用于注入普通属性值。
依赖注入的数据类型有如下三种
普通数据类型例如: String、int、 boolean等通过value属性指定引用数据类型例如: UserDaolmpl、DataSource等通过ref属性指定。集合数据类型例如: List、Map、Properties等。
注property和constructor-arg的name属性和参数的名字必须要一样
public class UserDaoImpl implements UserDao {//注入一个List集合private ListString list;public void setList(ListString list) {this.list list;}//注入一个字符串类型的Set集合private SetString userSet;public void setUserSet(SetString userSet) {this.userSet userSet;}//注入一个UserDao类的Set集合private SetUserDao userDaoSet;public void setUserDaoSet(SetUserDao userDaoSet) {this.userDaoSet userDaoSet;}//注入一个map集合private MapString,UserDao map;public void setMap(MapString,UserDao map) {this.map map;}//注入Propertiesprivate Properties properties;public void setProperties(Properties properties){this.properties properties;}public void show(){System.out.println(list);System.out.println(userSet);System.out.println(userDaoSet);System.out.println(map);System.out.println(properties);}
}?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:utilhttp://www.springframework.org/schema/utilxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsdbean iduserDao classcom.Smulll.Dao.Impl.UserDaoImpl!--配置注入一个List类型的集合--property namelistlistvalueaaa/valuevaluesss/value/list/property!--配置注入一个Set集合--property nameuserSetsetvalueasdsa/valuevalue11111/valuevalue22222/valuevalue33333/value/set/property!--配置注入一个UserDao类的Set集合--property nameuserDaoSetsetref beanuserDao1/refref beanuserDao2/refref beanuserDao3/refref beanuserDao4/ref/set/property!--配置注入一个map集合--property namemapmapentry keym1 value-refuserDao1/entryentry keym2 value-refuserDao2/entryentry keym3 value-refuserDao3/entryentry keym4 value-refuserDao4/entry/map/property!--配置一个properties键值都是string的键值对--property namepropertiespropsprop keyp1p111/propprop keyp2p222/propprop keyp3p333/propprop keyp4p444/prop/props/property/beanbean iduserDao1 classcom.Smulll.Dao.Impl.UserDaoImpl/beanbean iduserDao2 classcom.Smulll.Dao.Impl.UserDaoImpl/beanbean iduserDao3 classcom.Smulll.Dao.Impl.UserDaoImpl/beanbean iduserDao4 classcom.Smulll.Dao.Impl.UserDaoImpl/bean
/beansTest
public void demo5(){ClassPathXmlApplicationContext classPathXmlApplicationContext new ClassPathXmlApplicationContext(beans.xml);UserDao userDao (UserDao)classPathXmlApplicationContext.getBean(userDao);userDao.show();
}2.8.2、自动装配
扩展自动装配方式
如果被注入的属性类型是Bean引用的话那么可以在bean标签中使用autowire属性去配置自动注入方式属 性值有两个:
byName通过属性名自动装配即去匹配 setXxx 与idxxx (namexxx)是否一致;byType通过Bean的类型从容器中匹配匹配出多个相同Bean类型时报错。
private UserService userService;
public void setUserService(UserService userService){this.userService userService;
}bean iduserDao classcom.Smulll.Dao.Impl.UserDaoImpl autowirebyName/bean
bean iduserService classcom.Smulll.service.Impl.UserServiceImpl/bean2.9、命名空间的种类
Spring的xml标签大体上分为两类一种是默认标签一种是自定义标签
默认标签:就是不用额外导入其他命名空间约束的标签例如bean标签自定义标签:就是需要额外引入其他命名空间约束并通过前缀引用的标签例如context:property-placeholder/标签
Spring的默认标签用到的是Spring的默认命名空间
?xml version1.0encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp: //www.w3.org/2001/xMschema-instancexsi:schemalocationhttp: //www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
/beans该命名空间约束下的默认标签如下
标签作用beans一般作为xml配置根标签其他标签都是该标签的子标beanBean的配置标签上面已经详解了此处不再阐述import外部资源导入标签alias指定Bean的别名标签使用较少
2.9.1、beans的profile属性切换环境
beans标签除了经常用的做为根标签外还可以嵌套在根标签内使用profile属性切换开发环境
!--配置测试环境下需要加载的Bean实例--
beans profiletest/beans
!--配置开发环境下需要加载的Bean实例--
beans profiledev/beans可以使用以下两种方式指定被激活的环境
使用命令行动态参数虚拟机参数位置加载 -Dspring.profiles.activetest使用代码的方式设置环境变量 System.setProperty(spring.profiles.active,test)
2.9.2、import标签
import标签用于导入其他配置文件项目变大后就会导致一个配置文件内容过多可以将一个配置文件根据业务某块进行拆分拆分后最终通过import标签导入到一个主配置文件中项目加载主配置文件就连同import导入的文件一并加载了
!--导入用户模块配置文件--
import resourceclasspath:UserModuleApplicationcontext.xml/
!--导入商品模块配置文件--
import resourceclasspath:ProductModuleApplicationcontext.xml/2.9.3、alias标签
alias标签是为某个Bean添加别名与在bean标签上使用name属性添加别名的方式一样我们为UserServicelmpl指定四个别名: aaa、bbb、xxx、yyy
!--配置UserService--
bean iduserService nameaaa,bbb classcom.itheima.service.imp1.UserserviceImp1property nameuserDao refuserDao/
/bean
!--指定别名--
alias nameuserservice aliasxxx/
alias nameuserservice aliasyyy/2.9.1、自定义命名空间的使用步骤
Spring的自定义标签需要引入外部的命名空间并为外部的命名空间指定前缀使用前缀:标签形式的标签称之为自定义标签自定义标签的解析流程也是Spring xml扩展点方式之一
!--默认标签--
bean iduserDao classcom.itheima. dao .imp1.userDaoImpl /
!--自定义标签--
context:property-placeholder/
mvc:annotation-driven/
dubbo:application nameapplication/步骤
引入坐标引入jar包找命名空间xmlns和xsi通过前缀来引入自定义标签
三、Spring常用的三种getBean的API
方法定义返回值和参数Object getBean (String beanName)根据beanName从容器中获取Bean实例要求容器中Bean唯一返回值为Object需要强转T getBean (Class type)根据Class类型从容器中获取Bean实例要求容器中Bean类型唯一返回值为Class类型实例无需强转T getBean (String beanNameClass type)根据beanName从容器中获得Bean实例返回值为Class类型实例无需强转
//根据beanName获取容器中的Bean实例需要手动强转
UserService userService (UserService)applicationContext.getBean(userService);
//根据Bean类型去容器中匹配对应的Bean实例如存在多个匹配Bean则报错
UserService userService2 applicationContext.getBean(UserService.class);
//根据beanName获取容器中的Bean实例指定Bean的Type类型
UserService userService3 applicationContext.getBean(userService,UserService.class) ;四、Spring配置非自定义Bean
以上在xml中配置的Bean都是自己定义的例如: UserDaolmplUserServicelmpl。但是在实际开发中有些功能类并不是我们自己定义的而是使用的第三方jar包中的那么这些Bean要想让Spring进行管理也需要对其进行配置
配置非自定义的Bean需要考虑如下两个问题
被配置的Bean的实例化方式是什么无参构造、有参构造、静态工厂方式还是实例化工厂方式被配置的Bean是否需要注入必要属性
4.1、DruidDatasource
配置Druid数据源交由Spring管理 导入Druid坐标
!--mysql驱动--
dependencygroupIdmysql/groupidartifactIdmysql-connector-java/artifactIdversion5.1.49/version
/dependency
!-- druid数据源--
dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.23/version
/dependency配置文件
bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName valuecom.mysql.cj.jdbc.Driver/propertyproperty nameurl valuejdbc:mysql://localhost:3306/mybatis/propertyproperty nameusername valuexxxxxx/propertyproperty namepassword valuexxxxxx/property
/bean4.2、Connection
Connection的产生是通过DriverManager的静态方法getConnection获取的所以我们要用静态工厂方式配置
bean classjava.lang.class factory-methodforNameconstructor-arg nameclassName valuecom.mysql.jdbc.Driver /
/bean
bean idconnection classjava.sql.DriverManager factory-methodgetConnection scopeprototypeconstructor-arg nameurl valuejdbc:mysql:///mybatis /constructor-arg nameuser valueroot/constructor-arg namepassword valueroot/
/bean4.3、Date
产生一个指定日期格式的对象原始代码如下
String currentTimeStr 2023-08-27 07:20:00 ;
SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);
Date date simpleDateFormat.parse(currentTimeStr);可以看成是实例工厂方式使用Spring配置方式产生Date实例
bean idsimpleDateFormat classjava.text.SimpleDateFormatconstructor-arg namepattern valueyyyy-MM-dd HH:mm:ss /
/bean
bean iddate factory-beansimpleDateFormat factory-methodparseconstructor-arg namesource value2023-08-27 07:20:00/
/bean4.4、SqlSessionFactory
配置SqlSessionFactory交由Spring管理 导入Mybatis相关坐标
dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.10/version
/dependency
dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.30/version
/dependency!--静态工厂方法--
bean idinputStream classorg.apache.ibatis.io.Resources factory-methodgetResourceAsStreamconstructor-arg nameresource valuemybatis-config.xml/constructor-arg
/bean
!--无参构造实例化--
bean idbuilder classorg.apache.ibatis.session.SqlSessionFactoryBuilder/bean
!--实例化工厂--
bean idfactory factory-beanbuilder factory-methodbuildconstructor-arg nameinputStream refinputStream/constructor-arg
/bean五、Bean实例化的基本流程
5.1、BeanDefinition
Spring容器在进行初始化时会将xml配置的bean的信息封装成一个BeanDefinition对象;所有的BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去;Spring框架在对该Map进行遍历使用反射创建Bean实例对象创建好的Bean对象存储在一个名为singletonObjects的Map集合中;当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。 DefaultListableBeanFactory对象内部维护着一个Map用于存储封装好的BeanDefinitionMap
public class DefaultListableBeanFactory extends ... implements ... {//存储bean标签对应的BeanDefinition对象//key:是Bean的beanName,value:是Bean定义对象BeanDefinitionprivate final MapString,BeanDefinition beanDefinitionMap;
}Spring框架会取出beanDefinitionMap中的每个BeanDefinition信息反射构造方法或调用指定的工厂方法生成Bean实例对象所以只要将BeanDefinition注册到beanDefinitionMap这个Map中,Spring就会进行对应的Bean的实例化操作
5.2、单例池和流程总结
Bean实例及单例池singletonObjectsbeanDefinitionMap中的BeanDefinition会被转化成对应的Bean实例对象存储到单例池singletonObjects中去在DefaultListableBeanFactory的上四级父类 DefaultSingletonBeanRegistry中维护着singletonObjects 源码如下:
public class DefaultSingletonBeanRegistry extends ... implements ... {
//存储Bean实例的单例池
key :是Bean的beanName,value:是Bean的实例对象
private final MapString,object singleton0bjects new ConcurrentHashMap(256)基本流程
加载xml配置文件解析获取配置中的每个bean的信息封装成一个个的BeanDefinition对象;将BeanDefinition存储在一个名为beanDefinitionMap的MapString,BeanDefinition中;ApplicationContext底层遍历beanDefinitionMap创建Bean实例对象;创建好的Bean实例对象被存储到一个名为singletonObjects的MapString,Object中;当执行applicationContext.getBean(beanName)时从singletonObjects去匹配Bean实例返回。 六、Spring的Bean工厂后处理器
6.1、入门
Spring的后处理器是Spring对外开发的重要扩展点允许我们介入到Bean的整个实例化流程中来以达到动态注册BeanDefinition动态修改BeanDefinition以及动态修改Bean的作用。Spring主要有两种后处理器:
BeanFactoryPostProcessor: Bean工厂后处理器在BeanDefinitionMap填充完毕Bean实例化之前执行;BeanPostProcessor: Bean后处理器一般在Bean实例化之后填充到单例池singletonObjects之前执行。
Bean工厂后处理器-BeanFactoryPostProcessor BeanFactoryPostProcessor是一个接口规范实现了该接口的类只要交由Spring容器管理的话那么Spring就会回调该接口的方法用于对BeanDefinition注册和修改的功能。
BeanFactoryPostProcessor定义如下
public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}6.2、注册BeanDefinition
使用这种方法可以不用再spring容器内在创建一个类的bean标签
public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println(beandefinitionMap填充完毕后回调该方法);//1.注册一个beandefinition 创建一个RootBeanDefinition()对象RootBeanDefinition rootBeanDefinition new RootBeanDefinition();rootBeanDefinition.setBeanClassName(com.Smulll.Dao.Impl.processorImpl);//2.将beanFactory强转成DefaultListableBeanFactory类型DefaultListableBeanFactory beanFactory1 (DefaultListableBeanFactory) beanFactory;beanFactory1.registerBeanDefinition(processor,rootBeanDefinition);}
}Test
public void demo2(){ClassPathXmlApplicationContext classPathXmlApplicationContext new ClassPathXmlApplicationContext(beans.xml);Object processor classPathXmlApplicationContext.getBean(processor);System.out.println(processor);
}bean classcom.Smulll.processor.MyBeanFactoryProcessor/bean6.3、BeanDefinitionRegistryPostProcessor
Spring提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {//创建一个RootBeanDefinition()对象RootBeanDefinition rootBeanDefinition new RootBeanDefinition();rootBeanDefinition.setBeanClassName(com.Smulll.Dao.Impl.processorImpl);//不需要强转就可以创建一个BeanbeanDefinitionRegistry.registerBeanDefinition(personDao,rootBeanDefinition);}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}
}6.4、完善实例化流程图
BeanFactoryPostProcessor在SpringBean的实例化过程中的体现 6.5、自定义Component
要求
自定义MyComponent注解使用在类上;使用资料中提供好的包扫描器工具BaseClassScanUtils完成指定包的类扫描;自定义BeanFactoryPostProcessor完成注解MyComponent的解析解析后最终被Spring管理。
BaseClassScanUtils
public class BaseClassScanUtils {//设置资源规则private static final String RESOURCE_PATTERN /**/*.class;public static MapString, Class scanMyComponentAnnotation(String basePackage) {//创建容器存储使用了指定注解的Bean字节码对象MapString, Class annotationClassMap new HashMapString, Class();//spring工具类可以获取指定路径下的全部类ResourcePatternResolver resourcePatternResolver new PathMatchingResourcePatternResolver();try {String pattern ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX ClassUtils.convertClassNameToResourcePath(basePackage) RESOURCE_PATTERN;Resource[] resources resourcePatternResolver.getResources(pattern);//MetadataReader 的工厂类MetadataReaderFactory refractory new CachingMetadataReaderFactory(resourcePatternResolver);for (Resource resource : resources) {//用于读取类信息MetadataReader reader refractory.getMetadataReader(resource);//扫描到的classString classname reader.getClassMetadata().getClassName();Class? clazz Class.forName(classname);//判断是否属于指定的注解类型if(clazz.isAnnotationPresent(MyComponent.class)){//获得注解对象MyComponent annotation clazz.getAnnotation(MyComponent.class);//获得属value属性值String beanName annotation.value();//判断是否为if(beanName!null!beanName.equals()){//存储到Map中去annotationClassMap.put(beanName,clazz);continue;}//如果没有为,那就把当前类的类名作为beanNameannotationClassMap.put(clazz.getSimpleName(),clazz);}}} catch (Exception exception) {}return annotationClassMap;}public static void main(String[] args) {MapString, Class stringClassMap scanMyComponentAnnotation(com.Smulll);System.out.println(stringClassMap);}
}Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
public interface MyComponent {String value();
}MyComponent(One)
public class OneBean {
}七、Spring的Bean后处理器
7.1、概念和入门
Bean被实例化后到最终缓存到名为singletonObjects单例池之前中间会经过Bean的初始化过程例如:属性的填充、初始方法init的执行等其中有一个对外进行扩展的点BeanPostProcessor我们称为Bean后处理。跟上面的Bean工厂后处理器相似它也是一个接口实现了该接口并被容器管理的BeanPostProcessor会在流程节点上被Spring自动调用。
public class MyBeanPostProcesser implements BeanPostProcessor {Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(beanNamepostProcessBeforeInitialization);return null;}Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(beanNamepostProcessAfterInitialization);return null;}
}postProcessBeforeInitialization方法和postProcessAfterInitialization方法需要进行手动创建接口中实现的是null返回值的方法两者方法在bena创建之后执行
7.2、before和after方法的执行时机
先执行bean的构造方法执行before方法执行InitializingBean接口中的afterPropertiesSet()方法执行在xml文件中设置的Bean的init-method方法执行after方法 7.3、案例-日志功能增强 Processor类
package com.Smulll.processor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;import java.lang.reflect.Proxy;
import java.util.Date;public class TimelogBeanPostProcessor implements BeanPostProcessor {Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {//使用动态代理对目标Bean进行增强返回proxy对象进而储存导单例池singletonObjects中Object beanproxy Proxy.newProxyInstance(bean.getClass().getClassLoader(),bean.getClass().getInterfaces(),(proxy, method, args) - {//1.输出开始时间System.out.println(方法 method.getName() 开始时间 new Date());//2.执行目标方法Object result method.invoke(bean, args);//3.输出结束时间System.out.println(方法 method.getName() 结束时间 new Date());return result;});return beanproxy;}
}接口实现类
package com.Smulll.Dao.Impl;import com.Smulll.Dao.UserDao;
import com.Smulll.service.UserService;public class UserDaoImpl implements UserDao{public void show(){try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(执行了show方法。。。);}private UserService userService;public void setUserService(UserService userService){this.userService userService;}
}xml文件
bean iduserDao classcom.Smulll.Dao.Impl.UserDaoImpl init-methodinit/beanbean classcom.Smulll.processor.TimelogBeanPostProcessor/bean测试方法
Test
public void demo2(){ClassPathXmlApplicationContext classPathXmlApplicationContext new ClassPathXmlApplicationContext(applicationContext.xml);UserDao userDao (UserDao)classPathXmlApplicationContext.getBean(userDao);userDao.show();
}7.4、再次完善实例化基本流程图
BeanPostProcessor在 SpringBean的实例化过程中的体现 八、SpringBean的生命周期
8.1、概述
Spring Bean的生命周期是从Bean 实例化之后即通过反射创建出对象之后导Bean成为一个完整对象最终储存到单例池中这个过程被称为SpringBean的生命周期。Spring Bean的生命周期大体上分为三个阶段:
Bean的实例化阶段: Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的是否不是FactoryBean等最终将一个普通的singleton的Bean通过反射进行实例化Bean的初始化阶段∶Beane创建之后还仅仅是个”半成品“还需要对Bean实例的属性进行填充、执行一些Aware接口方法、执行BeanPostProcessor方法、执行InitializingBean接口的初始化方法、执行自定义初始化init方法等。该阶段是Spring最具技术含量和复杂度的阶段Aop增强功能后面要学习的Spring的注解功能等、spring高频面试题Bean的循环引用问题都是在这个阶段体现的Bean的完成阶段:经过初始化阶段Bean就成为了一个完整的Spring Bean被存储到单例池singletonObjects中去了即完成了Spring Bean的整个生命周期。
8.2、初始化阶段执行步骤
由于Bean的初始化阶段的步骤比较复杂所以着重研究Bean的初始化阶段 Spring Bean的初始化过程涉及如下几个过程:
Bean实例的属性填充Aware接口属性注入BeanPostProcessor的before()方法回调lnitializingBean接口的初始化方法回调自定义初始化方法init回调BeanPostProcessor的after()方法回调
8.3、初始化阶段注入属性信息封装
BeanDefinition 中有对当前Bean实体的注入信息通过属性propertyValues进行了存储
bean iduserDao classcom.Smulll.Dao.Impl.UserDaoImpl/beanbean iduserService classcom.Smulll.service.Impl.UserServiceImplproperty namedao refuserDao/propertyproperty nameusername valueAAA/property
/bean例如UserService的属性信息
8.4、属性注入的三种情况
Spring在进行属性注入时会分为如下几种情况:
注入普通属性String、int或存储基本类型的集合时直接通过set方法的反射设置进去;注入单向对象引用属性时从容器中getBean获取后通过set方法反射设置进去如果容器中没有则先创建被注入对象Bean实例完成整个生命周期后在进行注入操作注入双向对象引用属性时就比较复杂了涉及了循环引用循环依赖问题下面会详细阐述解决方案。
8.5、单向对象注入的代码验证
public class UserServiceImpl implements UserService{private UserDao dao;private String username;public UserServiceImpl() {System.out.println(实例化UserService);}public UserServiceImpl(UserDao dao, String username) {this.dao dao;this.username username;}public void setDao(UserDao dao) {System.out.println(执行setDao方法);this.dao dao;}public void setUsername(String username) {this.username username;}
}public class UserDaoImpl implements UserDao{public UserDaoImpl() {System.out.println(实例化UserDao);}
}user的bean在userService的前面
bean iduserDao classcom.Smulll.Dao.Impl.UserDaoImpl/beanbean iduserService classcom.Smulll.service.Impl.UserServiceImplproperty namedao refuserDao/propertyproperty nameusername valueAAA/property
/bean执行结果 user的bean在userService的后面
bean iduserService classcom.Smulll.service.Impl.UserServiceImplproperty namedao refuserDao/propertyproperty nameusername valueAAA/property
/beanbean iduserDao classcom.Smulll.Dao.Impl.UserDaoImpl/bean8.6、循环依赖概念及解决方案
多个实体之间相互依赖并形成闭环的情况就叫做 “循环依赖”也叫做 “循环引用” bean iduserService classcom.Smulll.service.Impl.UserServiceImplproperty namedao refuserDao/property
/beanbean iduserDao classcom.Smulll.Dao.Impl.UserDaoImplproperty nameservice refuserService/property
/beanpublic class UserDaoImpl implements UserDao{private UserService service; public void setService(UserService service){this.service service;}
}
public class UserServiceImpl implements UserService{private UserDao dao;public void setDao(UserDao dao) {this.dao dao;}
}8.7、三级缓存的设计原理
Spring提供了三级缓存存储完整Bean实例和半成品Bean实例用于解决循环引用问题 在DefaultListableBeanFactory的上四级父类DefaultSingletonBeanRegistry中提供如下三个Map:
public class DefaultsingletonBeanRegistry ... {//1、最终存储单例Bean成品的容器即实例化和初始化都完成的Bean称之为一级缓存MapString,Object singletonObjects new ConcurrentHashMap(256);//2、早期Bean单例池缓存半成品对象且当前对象已经被其他对象引用了称之为二级缓存MapString,Object earlySingletonObjects new ConcurrentHashMap(16);//3、单例Bean的工厂池缓存半成品对象对象未被引用使用时在通过工厂创建Bean称之为三级缓存MapString,ObjectFactory? singletonFactories new HashMap(16);
}8.8、循环依赖源码流程剖析
UserService和UserDao循环依赖的过程结合上述三级缓存描述一下
UserService 实例化对象但尚未初始化将UserService存储到三级缓存;UserService 属性注入需要UserDao从缓存中获取没有UserDao;UserDao 实例化对象但尚未初始化将UserDao存储到到三级缓存;UserDao 属性注入需要UserService从三级缓存获取UserServiceUserService从三级缓存移入二级缓存;UserDao执行其他生命周期过程最终成为一个完成Bean存储到一级缓存删除二三级缓存;UserService注入UserDao;UserService执行其他生命周期过程最终成为一个完成Bean存储到一级缓存删除二三级缓存。
8.9、Aware接口
Aware接口是一种框架辅助属性注入的一种思想其他框架中也可以看到类似的接口。框架具备高度封装性我们接触到的一般都是业务代码一个底层功能API不能轻易的获取到但是这不意味着永远用不到这些对象如果用到了就可以使用框架提供的类似Aware的接口让框架给我们注入该对象。
Aware接口回调方法作用ServletContextAwaresetServletContext(ServletContext context)Spring框架回调方法注入ServletContext对象,web环境下才生效BeanFactoryAwaresetBeanFactory(BeanFactory factory)Spring框架回调方法注入beanFactory对象BeanNameAwaresetBeanName(String beanName)Spring框架回调方法注入当前Bean在容器中的beanNameApplicationContextAwaresetApplicationContext(ApplicationContext applicationContext)Spring框架回调方法注入applicationContext对象
九、Spring IoC容器实例化Bean整体流程图 十、Spring xml方式整和第三方框架
xml整合第三方框架有两种整合方案
不需要自定义名空间不需要使用Spring的配置文件配置第三方框架本身内容例如: MyBatis;需要引入第三方框架命名空间需要使用Spring的配置文件配置第三方框架本身内容例如:Dubbo。
10.1、Mybatis整合Spring实现
Spring整合MyBatis之前已经在Spring中简单的配置了SqlSessionFactory但是这不是正规的整合方式,MyBatis提供了mybatis-spring.jar专门用于两大框架的整合。 Spring整合MyBatis的步骤如下:
导入MyBatis整合Spring的相关坐标;
dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactId!--注意版本因为版本过低的原因在这里卡了很久--version3.0.1/version
/dependency
dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.25.RELEASE/version
/dependency编写Mapper和Mapper.xml;配置SqlSessionFactoryBean和MapperScannerConfigurer;
bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName valuecom.mysql.cj.jdbc.Driver/propertyproperty nameurl valuejdbc:mysql://localhost:3306/mybatis2/propertyproperty nameusername valueroot/propertyproperty namepassword value123456/property
/bean
!--配置SqlSessionFactoryBean作用将SqlSessionFactory存储到spring容器--
bean classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource/property
/bean
!--MapperScannerConfigurer作用扫描指定的包产生Mapper对象存储到Spring容器--
bean classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuecom.Smulll.mapper/property
/beanbean iduserService classcom.Smulll.service.Impl.UserServiceImplproperty namecarMapper refcarMapper/property
/bean
编写测试代码
10.2、Mybatis整合Spring源码解析
整合包里提供了一个SqlSessionFactoryBean和一个扫描Mapper的配置对象SqlSessionFactoryBean一旦被实例化就开始扫描Mapper并通过动态代理产生Mapper的实现类存储到Spring容器中。相关的有如下四个类:
sqlSessionFactoryBean:需要进行配置用于提供SqlSessionFactory;MapperScannerConfigurer:需要进行配置用于扫描指定mapper注册BeanDefinition;MapperFactoryBean: Mapper的FactoryBean获得指定Mapper时调用getObject方法;ClassPathMapperScanner: definition.setAutowireMode(2)修改了自动注入状态所以MapperFactoryBean中的setSqlSessionFactory会自动注入进去。
10.3、加载外部properties文件
Spring整合其他组件时就不像MyBatis这么简单了例如Dubbo框架在于Spring进行整合时要使用Dubbo提供的命名空间的扩展方式自定义了一些Dubbo的标签
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:dubbohttp://dubbo.apache.org/schema/dubboxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbohttp://dubbo.apache.org/schema/dubbo/dubbo.xsd!-- 配置Dubbo应用信息 --dubbo:application nameyour-application-name /!-- 配置注册中心 --dubbo:registry addresszookeeper://127.0.0.1:2181 /!-- 配置服务提供者 --dubbo:protocol namedubbo port20880 /dubbo:service interfacecom.example.YourServiceInterface refyourServiceBean /!-- 配置其他Bean --!-- 消费者配置 --dubbo:consumer checkfalse timeout1000 retries0/
/beans通过配置context文件来加载外部properties文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!--通过context加载properties文件--context:property-placeholder locationclasspath:jdbc.properties/bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/bean!--配置SqlSessionFactoryBean作用将SqlSessionFactory存储到spring容器--bean classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource/property/bean!--MapperScannerConfigurer作用扫描指定的包产生Mapper对象存储到Spring容器--bean classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuecom.Smulll.mapper/property/beanbean iduserService classcom.Smulll.service.Impl.UserServiceImplproperty namecarMapper refcarMapper/property/bean
/beans
10.4、自定义空间步骤
将自定义标签的约束与物理约束文件与网络约束名称的约束以键值对形式存储到一个spring.schemas文件里该文件存储在类加载路径的META-INF里Spring会自动加载到;将自定义命名空间的名称与自定义命名空间的处理器映射关系以键值对形式存在到一个叫spring.handlers文件里该文件存储在类加载路径的 META-INF里Spring会自动加载到;准备好NamespaceHandler如果命名空间只有一个标签那么直接在parse方法中进行解析即可一般解析结果就是注册该标签对应的BeanDefinition。如果命名空间里有多个标签那么可以在init方法中为每个标签都注册一个BeanDefinitionParser在执行NamespaceHandler的parse方法时在分流给不同的 BeanDefinitionParser进行解析(重写doParse方法即可)。
10.5、自定义命名空间案例 步骤分析
确定命名空间名称、schema虚拟路径、标签名称;编写schema约束文件haohao-annotation.xsd在类加载路径下创建META目录编写约束映射文件spring.schemas和处理器映射文件spring.handlers编写命名空间处理器HaohaoNamespaceHandler在init方法中注册HaohaoBeanDefinitionParser编写标签的解析器HaohaoBeanDefinitionParser在parse方法中注册HaohaoBeanPostProcessor编写HaohaoBeanPostProcessor 以上五步是框架开发者写的以下是框架使用者写的 在applicationContext.xml配置文件中引入命名空间在applicationContext.xml配置文件中使用自定义的标签