ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Spring 框架核心详解:IOC、DI

2026/9/27 10:22:52 拓冰建站 浏览量
Spring 框架核心详解:IOC、DI 温馨提示学习所需要的jar文件下载链接如下通过网盘分享的文件lib链接: SSMjar包下载链接Spring 框架核心详解IOC、DI1. IOC控制反转1.1 概念与原理1.2 容器实现对比1.3 代码案例XML 配置 IOC2. DI依赖注入2.1 概念与原理2.2 注入方式详解① 有参构造注入② Set 方法注入推荐③ 特殊符号与 CDATA④ 内部 Bean 与外部 Bean⑤ 集合类型注入⑥ 集合提取复用⑦ FactoryBean工厂 Bean3. Bean 作用域Scope4. Bean 生命周期4.1 完整流程4.2 代码验证5. 自动装配6. 外部属性文件数据库连接池7. 注解开发7.1 创建 Bean 的注解7.2 属性注入注解7.3 开启组件扫描8. 完全注解开发零 XML9、Spring Bean XML 配置编程题题目描述题目要求参考答案applicationContext.xmlCourseManager 类1. IOC控制反转1.1 概念与原理是什么IOCInversion of Control即控制反转是一种设计思想。它将对象创建和管理的控制权从程序代码转移到了外部容器Spring 容器。为什么传统开发中对象之间的依赖关系由代码硬编码如 new UserService()导致高耦合。IOC 通过工厂模式 反射 XML/注解配置让容器负责实例化对象并注入依赖从而降低耦合提升可测试性和可维护性。怎么做定义 Bean 配置XML 或注解启动容器从容器获取对象。1.2 容器实现对比Spring 提供两种核心容器接口特性BeanFactoryApplicationContext加载时机懒加载getBean 时创建预加载启动时创建所有单例 Bean功能基础 IOC 功能继承 BeanFactory支持国际化、事件、AOP 等适用场景资源受限环境极少用企业级开发标准选择最佳实践开发中始终使用 ApplicationContext避免运行时创建对象的性能抖动。1.3 代码案例XML 配置 IOC// 1. 业务接口publicinterfaceUserService{voidaddUser();}// 2. 业务实现publicclassUserServiceImplimplementsUserService{OverridepublicvoidaddUser(){System.out.println(用户添加成功);}}!-- 3. Spring XML 配置 (applicationContext.xml) --beansxmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!-- id: 唯一标识, class: 全限定类名 --beaniduserServiceclasscom.example.service.UserServiceImpl//beans// 4. 测试代码publicclassIocTest{publicstaticvoidmain(String[]args){// 加载配置文件此时对象已创建ApplicationContext 特性ApplicationContextcontextnewClassPathXmlApplicationContext(applicationContext.xml);// 从容器获取对象无需 newUserServiceuserService(UserService)context.getBean(userService);userService.addUser();// 输出: 用户添加成功}}2. DI依赖注入2.1 概念与原理是什么DIDependency Injection是 IOC 的具体实现方式。容器在运行期间将对象依赖的外部资源如其他 Bean、配置值注入到对象中。为什么解耦对象创建与依赖获取支持面向接口编程便于单元测试Mock 注入。2.2 注入方式详解① 有参构造注入publicclassUserDao{privateStringdbName;// 必须提供有参构造publicUserDao(StringdbName){this.dbNamedbName;}}!-- XML: 使用 constructor-arg --beaniduserDaoclasscom.example.dao.UserDaoconstructor-argnamedbNamevaluemysql_db//bean② Set 方法注入推荐publicclassUserServiceImplimplementsUserService{privateUserDaouserDao;// 必须提供 Set 方法publicvoidsetUserDao(UserDaouserDao){this.userDaouserDao;}}!-- XML: 使用 property --beaniduserServiceclasscom.example.service.UserServiceImplpropertynameuserDaorefuserDao/!-- ref 引用其他 Bean --/bean③ 特殊符号与 CDATA!-- 注入包含 等特殊字符的字符串 --propertynamesqlvalue![CDATA[SELECT * FROM user WHERE age 18]]/value/property④ 内部 Bean 与外部 Bean!-- 外部 Bean可被其他 Bean 引用 --beaniduserDaoclasscom.example.dao.UserDao/!-- 内部 Bean仅当前 Bean 可用无 id --beanidorderServiceclasscom.example.service.OrderServicepropertynameuserDaobeanclasscom.example.dao.UserDao/!-- 内部 Bean --/property/bean⑤ 集合类型注入publicclassConfigManager{privateListStringservers;privateMapString,Stringprops;// Setters...}beanidconfigManagerclasscom.example.config.ConfigManager!-- List 注入 --propertynameserverslistvalue192.168.1.1/valuevalue192.168.1.2/value/list/property!-- Map 注入 --propertynamepropsmapentrykeyenvvalueprod/entrykeyversionvalue1.0//map/property/bean⑥ 集合提取复用!-- 1. 定义集合片段 --util:listidserverListvalue192.168.1.1/valuevalue192.168.1.2/value/util:list!-- 2. 引用集合 --beanidconfigManagerclasscom.example.config.ConfigManagerpropertynameserversrefserverList//bean!-- 需引入 util 命名空间 --⑦ FactoryBean工厂 Bean是什么Spring 提供的特殊 Bean用于封装复杂对象的创建逻辑如 MyBatis 的 SqlSessionFactoryBean。区别普通 Bean 返回自身FactoryBean 返回 getObject() 的结果。publicclassMyFactoryBeanimplementsFactoryBeanUserDao{OverridepublicUserDaogetObject()throwsException{// 复杂创建逻辑如读取配置、代理等returnnewUserDao(dynamic_db);}OverridepublicClass?getObjectType(){returnUserDao.class;}OverridepublicbooleanisSingleton(){returntrue;}}!-- 获取的是 UserDao而非 MyFactoryBean --beaniduserDaoclasscom.example.factory.MyFactoryBean/3. Bean 作用域Scope值说明线程安全singleton默认。容器内唯一实例非线程安全避免定义可变状态prototype每次 getBean 创建新实例相对安全但容器不管理销毁beaniduserServiceclasscom.example.service.UserServiceImplscopeprototype/注意Web 环境下还有 request、session、globalSession 作用域。4. Bean 生命周期4.1 完整流程实例化调用无参构造器。属性赋值调用 Set 方法注入依赖。Aware 接口回调如 BeanNameAware、ApplicationContextAware。前置处理BeanPostProcessor.postProcessBeforeInitialization()。初始化PostConstruct / init-method / InitializingBean.afterPropertiesSet()。后置处理BeanPostProcessor.postProcessAfterInitialization()AOP 代理在此生成。使用对象就绪。销毁容器关闭时PreDestroy / destroy-method / DisposableBean.destroy()。4.2 代码验证publicclassLifeCycleBeanimplementsInitializingBean,DisposableBean{publicLifeCycleBean(){System.out.println(1. 构造器);}publicvoidsetConfig(Stringconfig){System.out.println(2. Set属性: config);}OverridepublicvoidafterPropertiesSet(){System.out.println(4. InitializingBean.afterPropertiesSet);}publicvoidcustomInit(){System.out.println(5. 自定义 init-method);}Overridepublicvoiddestroy(){System.out.println(7. DisposableBean.destroy);}publicvoidcustomDestroy(){System.out.println(8. 自定义 destroy-method);}}beanidlifeCycleBeanclasscom.example.bean.LifeCycleBeaninit-methodcustomInitdestroy-methodcustomDestroypropertynameconfigvaluetest//bean5. 自动装配模式规则缺点byName属性名 Bean ID命名不规范易失败byType属性类型 Bean 类型多个同类型 Bean 报错!-- 按名称自动装配 --beaniduserServiceclasscom.example.service.UserServiceImplautowirebyName/!-- 容器需存在 iduserDao 的 Bean --现代开发建议XML 自动装配已少用推荐注解 Autowired。6. 外部属性文件数据库连接池为什么环境相关配置URL、密码不应硬编码需外部化。# db.properties db.drivercom.mysql.cj.jdbc.Driver db.urljdbc:mysql://localhost:3306/test db.usernameroot db.password123456!-- 引入属性文件 --context:property-placeholderlocationclasspath:db.properties/!-- 使用 ${} 占位符 --beaniddataSourceclasscom.alibaba.druid.pool.DruidDataSourcepropertynamedriverClassNamevalue${db.driver}/propertynameurlvalue${db.url}/propertynameusernamevalue${db.username}/propertynamepasswordvalue${db.password}//bean7. 注解开发7.1 创建 Bean 的注解注解语义层级Component通用组件任意Service业务逻辑层ServiceRepository数据访问层DAOController控制层Web四者功能相同仅语义区分便于 AOP 切面定向拦截。7.2 属性注入注解ServicepublicclassUserServiceImplimplementsUserService{// 1. Autowired: 按类型注入AutowiredprivateUserDaouserDao;// 2. Qualifier: 指定 Bean ID配合 AutowiredAutowiredQualifier(mysqlUserDao)privateUserDaospecificDao;// 3. Resource: JSR-250按名称注入name 属性Resource(nameuserDao)privateUserDaoanotherDao;}7.3 开启组件扫描!-- 扫描指定包 --context:component-scanbase-packagecom.example/8. 完全注解开发零 XML是什么使用 Java 配置类替代 XML实现纯注解 IOC。怎么做Configuration ComponentScan AnnotationConfigApplicationContext。// 1. 配置类ConfigurationComponentScan(basePackagescom.example)publicclassSpringConfig{// 相当于 bean 标签BeanpublicUserDaouserDao(){returnnewUserDao(annotation_db);}}// 2. 测试publicclassAnnotationTest{publicstaticvoidmain(String[]args){// 加载配置类而非 XMLApplicationContextctxnewAnnotationConfigApplicationContext(SpringConfig.class);UserServiceservicectx.getBean(UserService.class);service.addUser();}}Spring Boot 基础SpringBootApplication 本质就是 Configuration ComponentScan EnableAutoConfiguration。9、Spring Bean XML 配置编程题题目描述已知以下两个 Java 类packagecom.example.bean;publicclassTeacher{privateintid;privateStringname;// 省略 getter/setter}publicclassCourse{privateintid;privateStringname;privateTeacherteacher;// 省略 getter/setter}题目要求请编写applicationContext.xml配置完成以下要求创建两个TeacherBeanid 分别为t1、t2创建两个CourseBeanid 分别为c1、c2每个Course通过ref注入对应的Teacher使用集合注入将两个Course放入一个List集合中注入到某个 Bean 的属性中。参考答案applicationContext.xml?xml version1.0 encodingUTF-8?beansxmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd!-- 创建两个 Teacher Bean --beanidt1classcom.example.bean.Teacherpropertynameidvalue1/propertynamenamevalue张老师//beanbeanidt2classcom.example.bean.Teacherpropertynameidvalue2/propertynamenamevalue李老师//bean!-- 创建两个 Course Bean通过 ref 注入对应的 Teacher --beanidc1classcom.example.bean.Coursepropertynameidvalue101/propertynamenamevalueJava程序设计/propertynameteacherreft1//beanbeanidc2classcom.example.bean.Coursepropertynameidvalue102/propertynamenamevalueSpring框架实战/propertynameteacherreft2//bean!-- 使用集合注入将两个 Course 放入 List注入到 CourseManager --beanidcourseManagerclasscom.example.bean.CourseManagerpropertynamecourseslistrefbeanc1/refbeanc2//list/property/bean/beansCourseManager 类importjava.util.List;publicclassCourseManager{privateListCoursecourses;publicListCoursegetCourses(){returncourses;}publicvoidsetCourses(ListCoursecourses){this.coursescourses;}}