当前位置: 首页 > news >正文

Spring DI/IOC核心原理详解

一.SpringDI/IOC


        1.SpringDI

        DI:(中文依赖注入):是对IOC概念的不同角度的描述。

主要是指应用程序在运行时,每一个bean对象都依赖IOC容器注入当前bean对象所需要的另外一个bean对象。

        作用:胶水,帮助springIOC容器,把所有依赖关系的javaBean对象粘合在一起。

实现步骤

        1.提供set方法

                1.1提供set方法

        2.配置标签

                2.1set注入

<property 属性名=“属性值”></property>

        属性:

                name=====>属性名

                value=====>属性值

                ref======>属性值的引用

实现方式

                1.set注入

                2.构造注入

                3.属性注入(不用)

                4.注解注入

支持的数据类型

                1.基本类型与String

                2.JavaBean对象注入(三层调用)

                3.复杂类型

具体实现:set注入

package com.itheima.service;
import com.itheima.dao.IUserDao;
import com.itheima.dao.UserDaoImp;public class UserServiceImp implements IUserService {
IUserDao userDao;public UserServiceImp(UserDaoImp userDao) {this.userDao = userDao;}public UserServiceImp() {}
//    public void setUserDao(IUserDao userDao){
//    this.userDao = userDao;
//}public void save() {System.out.println("===service的新增===");userDao.save();}
}
package com.itheima.dao;public class UserDaoImp implements IUserDao {public void save() {System.out.println("===dao的新增===");}
}
package com.itheima.controller;import com.itheima.service.IUserService;
import com.itheima.service.UserServiceImp;public class UserControllerImp implements IUserController {IUserService service;public UserControllerImp(UserServiceImp service) {this.service = service;}public UserControllerImp() {}//    public void setService(IUserService service){
//        this.service = service;
//    }public void save() {System.out.println("===controller的新增===");service.save();}
}<!--1.set注入-->
<!--    <bean id="dao" class="com.itheima.dao.UserDaoImp"></bean>-->
<!--    <bean id="service" class="com.itheima.service.UserServiceImp">-->
<!--        <property name="userDao" ref="dao"></property>-->
<!--    </bean>-->
<!--    <bean id="controller" class="com.itheima.controller.UserControllerImp">-->
<!--        <property name="service" ref="service"></property>-->
<!--    </bean>-->

构造注入

<!--  构造注入      -->
<!--    <bean id="dao1" class="com.itheima.dao.UserDaoImp"></bean>-->
<!--    <bean id="service1" class="com.itheima.service.UserServiceImp">-->
<!--        <constructor-arg name="userDao" ref="dao1"></constructor-arg>-->
<!--    </bean>-->
<!--    <bean id="controller1" class="com.itheima.controller.UserControllerImp">-->
<!--        <constructor-arg name="service" ref="service1"></constructor-arg>-->
<!--    </bean>-->
三层代码同上

        2.SpingIOC-管理bean

                bean的创建

                        1.通过反射调用类的无参构造方法(默认)。

                        2.通过指定的工厂,创建bean对象。

<!--    <bean id="singer1" class="com.itheima.pojo.Singer1" factory-bean="factory" factory-method="createSinger"></bean>-->
<!--    <bean id="factory" class="com.itheima.factory.SingerFactory"></bean>-->
package com.itheima.factory;import com.itheima.pojo.Singer;
import com.itheima.pojo.Singer1;public class SingerFactory {// 创建对象public Singer1 createSinger(){System.out.println("执行工厂方法");return new Singer1();}}

                        3.通过作用的指定的静态工厂,创建bean对象。

    <bean id="singer2" class="com.itheima.factory.SingerStaticFactory" factory-method="createSinger" scope="prototype"></bean>
package com.itheima.factory;import com.itheima.pojo.Singer;
import com.itheima.pojo.Singer1;public class SingerStaticFactory {// 创建对象public static Singer1 createSinger(){System.out.println("===>执行static工厂的工厂方法");return new Singer1();}}

                bean的作用域

                        含义bean的创建方式

                语法:<bean scope = ''属性值''></bean>

                        属性值

                                singleton单例(默认)

                                prototype多例

                                request请求

                                session会话

                bean的生命周期

                        1.实例化:创建对象

                        2.初始化

                                2.1接口初始化

                                2.2属性初始化

具体实现

package com.itheima.pojo;import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;// initializingBean接口
// DisposableBean接口
@Component
public class Teacher implements InitializingBean, DisposableBean {//实例化public Teacher() {System.out.println("===>生命周期:实例化");}//初始化(接口)public void afterPropertiesSet() throws Exception {System.out.println("===>生命周期:初始化1(接口)");}//销毁了(接口)public void destroy() throws Exception {System.out.println("===>生命周期:销毁了1(接口)");}
// 第二种初始化销毁方法//初始化(属性)@PostConstructpublic void doinit() throws Exception {System.out.println("===>生命周期:初始化2(属性)");}//销毁了(属性)@PreDestroypublic void dodestory() throws Exception {System.out.println("===>生命周期:销毁了2(属性)");}
}
<!--    <bean id="teacher" class="com.itheima.pojo.Teacher" init-method="doinit" destroy-method="dodestory"></bean>-->

                        3.操作使用

                        4.销毁了(实现同上)

                                4.1接口销毁了

                                4.2属性销毁了

3.Spring的配置(第一种纯xml的忽略)

        1.spring2.5前==xml ----第一天案例

        2.spring2.5后==xml+annotation ----Spring_Day02

        3.spring3.0后==annotation+javaConfig配置类 ----Spring_Day02

注意:spring 2.5后=xml+annotation

目的优化一下代码:

<bean id="" class="" init-method="" destroy-method="" scope="" autowire="">

<property></property>

<constructor-arg></constructor-arg>

</bean>

1.spring配置---第二种——spring2.5后==xml+annotation

        注解

                注入类

                替换:<bean id="" class=""></bean>

                位置:类

                语法:@Component(value="注入容器中的id,如果省略id为类名且首字母小写,value属性名可以省略")

举例

<bean id="user" class="com.apsourse.包.User"></bean>

||等价于||

@Component

Class User{}

注意: 不能单独使用,配合扫描使用

<context:component-scan base-pageage=""></context:component-scan>

        @Repository=====>注入数据访问层

        @Service=======>注入业务层

        Controller=======> 注入控制层

以上第三个注解与@Component功能语法一致

        注入数据

                @ value

                        含义:注入基本数据与String

                        替换:<property></property>

                        修饰:成员变量

                        语法:@Value("数据内容")

                                @Value("${动态获取}")

注意:不能单独用,配合加载配置文件标签

<context:property-placeholder location="classpath:jdbc.properties">/context:property-placeholder

@Autowired

        语法:@Autowired(required="true-默认,false,是否必须进行装配")

        修饰:成员变量

        含义:注入javaBean

注意:

        1.默认是按照类型装配,如果容器中有多个类型,则会自动切换为名称装配

        2.默认是按照类型装配,如果容器中有多个类型,则自动切换为名称装配,若名称也没有与之对应则会报异常NoUniqueBeanDefinitionException

        3.默认是按照类型装配,如果容器中没有一个 类可以与之匹配,则会报异常NoSuchBeanDefinitionException

其他注解

        @Primary

                含义:首选项,当类型冲突的情况下,此注解修饰的类被列为首选

                修饰:类

注意:不能单独使用,必须与@Component...联合使用

        @Qualifier(value="名称")

                含义:按照名称装配

                修饰:成员变量

注意:不能单独使用,必须与@Autowired联合使用


@Resource(name="名称")

        含义:按照名称装配

        修饰:成员变量

        注意:单独使用

@Scope

        含义:配置类的作用域

        修饰:类

注意:不能单独使用,必须与@Component...联合使用

        @Scope("prototype")

        @Scope("singleton")

        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

        @Scope(ConfigurableBeanFactory.SCOPE.SINGLETON)

        @PostConstruct:初始化,替换init-method

        @PreDestroy:销毁,替换destory-method

2.Spring配置---第三种(替代applicationContext.xml)文件——spring2.5后==>xml+annotation

@Configuration

        作用:指定当前类是一个配置类

        细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写

@ComponentScan

        作用:用于通过注解指定spring在创建容器时要扫描的包

        替换:<context:component-scan base-package="">/context:component-scan

@PropertySource

        作用:用于指定properties文件的位置

        替换:<context:property-placeholder location="">/context:property-placeholder

@Import

        作用:用于导入其他的配置类

        属性:value:用汉语指定其他配置类的字节码

        例子:@Import(SystemSpringConfig.class)

@Bean

        作用:用于把当前方法的返回值作为bean对象存入spring的容器中

        属性:name:用于指定bean的id,当不写时候,默认值时当前方法的名称

二.动态代理

        

 * 基于接口的动态代理:*  特点:字节码随用随创建,随用随加载*  作用:不修改源码的基础上对方法增强*  涉及的类:Proxy*  提供者:JDK官方*  如何创建代理对象:*      使用Proxy类中的newProxyInstance方法*  创建代理对象的要求:*      被代理类最少实现一个接口,如果没有则不能使用*  newProxyInstance方法的参数:*      ClassLoader:类加载器*          它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。*      Class[]:字节码数组*          它是用于让代理对象和被代理对象有相同方法。固定写法。*      InvocationHandler:用于提供增强的代码
 *  Object proxy=====》被代理对象的引用===(蔡徐坤对象)*  Method method====》执行的方法========(蔡徐坤唱歌方法)*  Object[] args====》执行方法的参数=====(蔡徐坤唱歌方法的参数)*  Object===========》执行方法的返回值===(蔡徐坤唱歌方法的返回值)* */* 作用:执行被代理对象的任何接口方法都会经过该方法* 方法参数的含义*  proxy   代理对象的引用*  method  当前执行的方法*  args    当前执行方法所需的参数*  Object  和被代理对象方法有相同的返回值*/       /*第一个参数:ZhouSeenImpl.class.getClassLoader()表示类加载器(ClassLoader),用于加载动态生成的代理类通常使用被代理类的类加载器,保证类加载的一致性第二个参数:ZhouSeenImpl.class.getInterfaces()表示被代理类实现的所有接口数组动态代理技术要求必须基于接口实现,代理对象会实现这些接口中定义的方法这里会返回ZhouSeenImpl类所实现的所有接口(包括ISinger)第三个参数:new InvocationHandler()这是一个接口实现,用于定义代理逻辑其中的invoke()方法会拦截所有对代理对象方法的调用可以在该方法中实现增强逻辑(如日志记录、性能监控、事务控制等),再决定是否调用原始对象的方法
*/
com.itheima.cglibtest.ISinger iSinger = (ISinger) Proxy.newProxyInstance(ZhouSeenImpl.class.getClassLoader(), ZhouSeenImpl.class.getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object obj = null;if (method.getName().equals("song")) {System.out.println("跳一段舞");obj = method.invoke(new ZhouSeenImpl(), args);}if (method.getName().equals("sing")) {System.out.println("打一个篮球");obj = method.invoke(new ZhouSeenImpl(), args);}return obj;}
});
iSinger.song();


文章转载自:

http://auoh4NtD.fbjnr.cn
http://GVYbGGPu.fbjnr.cn
http://lcG1DDVo.fbjnr.cn
http://5RiwJubT.fbjnr.cn
http://92rqgKlC.fbjnr.cn
http://XXZqLNu0.fbjnr.cn
http://Q4T4S1Yv.fbjnr.cn
http://5Rmh9Zow.fbjnr.cn
http://AHeamDyg.fbjnr.cn
http://ywOWuMc1.fbjnr.cn
http://HKZCMg61.fbjnr.cn
http://KU5BMB2y.fbjnr.cn
http://ruiP5nHR.fbjnr.cn
http://J8S1s4DF.fbjnr.cn
http://wNooZG1g.fbjnr.cn
http://K17TEcmw.fbjnr.cn
http://xx1bcx2C.fbjnr.cn
http://b1Ze2PBT.fbjnr.cn
http://tLAUXsEX.fbjnr.cn
http://f53XJaHi.fbjnr.cn
http://dAUhNmps.fbjnr.cn
http://yeaMn4fS.fbjnr.cn
http://BnzyNgP3.fbjnr.cn
http://DywVfq5j.fbjnr.cn
http://ec5Z2qyS.fbjnr.cn
http://7fvCrLhU.fbjnr.cn
http://TSncOFKW.fbjnr.cn
http://ojwhFykS.fbjnr.cn
http://shK9u4p2.fbjnr.cn
http://AMhdsRTe.fbjnr.cn
http://www.dtcms.com/a/377567.html

相关文章:

  • 基于多时间尺度的电动汽车光伏充电站联合分层优化调度(Matlab代码实现)
  • 【论文阅读】TrojVLM: Backdoor Attack Against Vision Language Models
  • 快速查看文件的MD5码
  • 多模态大模型研究每日简报【2025-09-10】
  • 股指期货合约的代码如何理解?
  • 基于Python的商品爬取与可视化系统
  • SEGGER_RTT相关的操作
  • vmware虚拟机 ubuntu固定usb转rndis网卡
  • Java管理事务方式
  • Spring Boot + Vue 项目中使用 Redis 分布式锁案例
  • Unity(①基础)
  • 【测量】知识点
  • 开始 ComfyUI 的 AI 绘图之旅-ControlNet(六)
  • 楼宇自控系统监控建筑变配电系统:功效体现在安全与节能层面
  • 分布式存储:RustFS与MinIO全面对比
  • 【第24话:定位建图】 SLAM回环检测方法及原理详细介绍
  • Electron 核心模块速查表
  • SafeEar:浙大和清华联合推出的AI音频伪造检测框架,错误率低至2.02%
  • vue2+jessibuca播放h265视频
  • 智普科技推出 Claude 用户平滑迁移方案,GLM-4.5 模型全面开放
  • IIS 部署 asp.net core 项目时,出现500.19、500.31问题的解决方案
  • ASP.NET Core 中的简单授权
  • 可遇不可求的自动化运维工具 | 2 | 实施阶段一:基础准备
  • Golang安装笔记
  • 【记录】Docker|Docker内部访问LInux主机上的Ollama服务
  • MySQL 日期时间类型:从入门到精通的核心指南
  • git 同时推送两个不同平台的版本管理库
  • SoC日志管理
  • 微服务网关全解析:从入门到实践
  • 《sklearn机器学习——数据预处理》类别特征编码