核心内容摘要
16岁,不止是风华正茂,更是未来的无限可能
Spring IOC控制反转详解
什么是 IOCIOCInversion of Control控制反转是一种设计思想不是什么技术实现。
它指的是将对象的创建、管理和依赖关系的控制权从程序代码本身转移到外部容器Spring 容器。
传统方式 vs IOC传统方式程序控制publicclassUserService{privateUserDaouserDaonewUserDao();// 自己创建依赖对象publicvoidaddUser(){userDao.save();}}IOC 方式容器控制publicclassUserService{AutowiredprivateUserDaouserDao;// 容器注入依赖对象publicvoidaddUser(){userDao.save();}}
IOC 的核心概念
控制反转控制指对象创建、依赖管理的控制权反转从程序代码反转到外部容器
依赖注入DIDependency InjectionDI 是 IOC 的实现方式指容器在创建对象时自动将依赖对象注入到目标对象中。
IOC 容器Spring 提供的容器实现负责管理 Bean 的生命周期和依赖关系。
Spring IOC 容器
两个核心接口// BeanFactory基础容器提供基本的 IOC 功能publicinterfaceBeanFactory{ObjectgetBean(Stringname);TTgetBean(ClassTrequiredType);booleancontainsBean(Stringname);// ...}// ApplicationContext高级容器扩展了更多功能publicinterfaceApplicationContextextendsBeanFactory{// 国际化支持StringgetMessage(Stringcode,Object[]args,Localelocale);// 资源加载ResourcegetResource(Stringlocation);// 事件发布voidpublishEvent(ApplicationEventevent);// ...}
常见的实现类//
ClassPathXmlApplicationContext从类路径加载配置ApplicationContextcontextnewClassPathXmlApplicationContext(applicationContext.xml);//
FileSystemXmlApplicationContext从文件系统加载配置ApplicationContextcontextnewFileSystemXmlApplicationContext(D:/config/applicationContext.xml);//
AnnotationConfigApplicationContext基于注解的配置ApplicationContextcontextnewAnnotationConfigApplicationContext(AppConfig.class);//
WebApplicationContextWeb 应用专用// 在 Spring Boot 中自动创建
Bean 的定义方式
XML 配置方式?xml version
0 encodingUTF-8?beansxmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w
org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!-- 定义 Bean --beaniduserServiceclasscom.example.UserService!-- 构造器注入 --constructor-argrefuserDao/!-- 属性注入 --propertynamenamevalue张三//beanbeaniduserDaoclasscom.example.UserDao//beans
注解方式推荐//
Component通用组件ComponentpublicclassUserService{AutowiredprivateUserDaouserDao;}//
Service服务层ServicepublicclassUserService{AutowiredprivateUserDaouserDao;}//
Repository数据访问层RepositorypublicclassUserDao{publicvoidsave(){// ...}}//
Controller控制层ControllerpublicclassUserController{AutowiredprivateUserServiceuserService;}//
Configuration配置类ConfigurationComponentScan(com.example)publicclassAppConfig{BeanpublicUserServiceuserService(){returnnewUserService(userDao());}BeanpublicUserDaouserDao(){returnnewUserDao();}}
依赖注入的方式
构造器注入推荐ServicepublicclassUserService{privatefinalUserDaouserDao;// Spring
3 单个构造器可省略 AutowiredAutowiredpublicUserService(UserDaouserDao){this.userDaouserDao;}}优点保证依赖不可变final保证对象初始化完成更容易测试
Setter 注入ServicepublicclassUserService{privateUserDaouserDao;AutowiredpublicvoidsetUserDao(UserDaouserDao){this.userDaouserDao;}}优点灵活可以在运行时修改适合可选依赖
字段注入ServicepublicclassUserService{AutowiredprivateUserDaouserDao;}缺点不能使用 final容易导致空指针不利于测试
方法注入ServicepublicclassUserService{privateUserDaouserDao;Autowiredpublicvoidinit(UserDaouserDao){this.userDaouserDao;}}
Bean 的作用域//
singleton默认单例整个容器只有一个实例Scope(singleton)publicclassUserService{}//
prototype原型每次获取都创建新实例Scope(prototype)publicclassUserService{}//
requestWeb 应用每个请求一个实例Scope(valueWebApplicationContext.SCOPE_REQUEST,proxyModeScopedProxyMode.TARGET_CLASS)publicclassUserService{}//
sessionWeb 应用每个会话一个实例Scope(valueWebApplicationContext.SCOPE_SESSION,proxyModeScopedProxyMode.TARGET_CLASS)publicclassUserService{}//
applicationWeb 应用ServletContext 生命周期Scope(valueWebApplicationContext.SCOPE_APPLICATION,proxyModeScopedProxyMode.TARGET_CLASS)publicclassUserService{}
Bean 的生命周期ComponentpublicclassUserServiceimplementsBeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{//
实例化构造器publicUserService(){System.out.println(
实例化);}//
设置属性AutowiredprivateUserDaouserDao;//
BeanNameAwareOverridepublicvoidsetBeanName(Stringname){System.out.println(
BeanNameAware.setBeanName: name);}//
BeanFactoryAwareOverridepublicvoidsetBeanFactory(BeanFactorybeanFactory){System.out.println(
BeanFactoryAware.setBeanFactory);}//
ApplicationContextAwareOverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext){System.out.println(
ApplicationContextAware.setApplicationContext);}//
BeanPostProcessor - 前置处理PostConstructpublicvoidpostConstruct(){System.out.println(
PostConstruct);}//
InitializingBeanOverridepublicvoidafterPropertiesSet(){System.out.println(
InitializingBean.afterPropertiesSet);}//
自定义初始化方法Bean(initMethodinit)publicvoidinit(){System.out.println(
自定义初始化方法);}// Bean 可以使用了//
PreDestroyPreDestroypublicvoidpreDestroy(){System.out.println(
PreDestroy);}//
DisposableBeanOverridepublicvoiddestroy(){System.out.println(
DisposableBean.destroy);}//
自定义销毁方法Bean(destroyMethodcleanup)publicvoidcleanup(){System.out.println(
自定义销毁方法);}}
IOC 容器启动流程//
创建容器ApplicationContextcontextnewAnnotationConfigApplicationContext(AppConfig.class);// 内部流程//
1 扫描配置类解析 Bean 定义//
2 注册 Bean 定义到 BeanDefinitionRegistry//
3 实例化单例 Bean非懒加载//
4 执行依赖注入//
5 执行初始化回调//
6 容器启动完成
自动装配Autowired
按类型装配AutowiredprivateUserDaouserDao;// 按类型查找
按名称装配AutowiredQualifier(userDaoImpl)// 指定 Bean 名称privateUserDaouserDao;
可选依赖Autowired(requiredfalse)// 不存在也不报错privateUserDaouserDao;
集合注入AutowiredprivateListUserDaouserDaoList;// 注入所有 UserDao 类型AutowiredprivateMapString,UserDaouserDaoMap;// Bean名称 - Bean实例
条件化注册 Bean//
ConditionalConfigurationpublicclassAppConfig{BeanConditional(WindowsCondition.class)// 满足条件才注册publicUserServicewindowsService(){returnnewWindowsService();}BeanConditional(LinuxCondition.class)publicUserServicelinuxService(){returnnewLinuxService();}}//
常用条件注解ConditionalOnClass(DataSource.class)// 类路径存在ConditionalOnMissingBean(DataSource.class)// 容器中不存在ConditionalOnProperty(nameapp.enabled,havingValuetrue)// 配置属性ConditionalOnExpression(${app.enabled:true})// SpEL 表达式
IOC 的优势
解耦// 不再需要手动创建和管理对象// 对象之间的关系由容器维护
便于测试// 可以轻松注入 Mock 对象TestpublicvoidtestUserService(){UserDaomockDaomock(UserDao.class);UserServiceservicenewUserService(mockDao);// 测试...}
配置化管理// 通过配置文件或注解管理对象// 便于维护和修改
AOP 支持// IOC 容器管理对象便于实现 AOPAspectComponentpublicclassLoggingAspect{Before(execution(* com.example.*.*(..)))publicvoidlogBefore(){// ...}}
十二、