spring-Ioc/di

本文介绍了Spring框架的发展历程,从2002年Rod Johnon创立至今,包括Spring框架的关键特性如AOP、IOC等。重点讲解了控制反转(IOC)的概念及其实现方式,包括如何通过XML配置文件定义bean及其属性,并探讨了不同类型的注入方式,如set注入、构造器注入和p命名空间注入。
spring发展

2002 Rod Johnon
Spring 2003 ,IOC Aop
产品:Spring data,spring boot,spring cloud,spring framework ,spring social

IOC:控制反转(亦称 DI:依赖注入)

对象创建发展史: new 创建 -> 简单工厂 -> 超级工厂(ioc)

控制反转 :将 创建对象、属性值 的方式 进行了翻转,从new、setXxx() 翻转为了 从springIOC容器getBean()
依赖注入:将属性值 注入给了属性,将属性 注入给了bean,将bean注入给了ioc容器;
无论要什么对象,都可以直接去springioc容器中获取,而不需要自己操作(new\setXxx())
因此之后的 ioc 分为2步:1 先给springioc中存放对象并赋值 2 拿

1、jar

开发spring至少需要使用的jar(5+1):
	spring-aop.jar		开发AOP特性时需要的JAR
	spring-beans.jar	处理Bean的jar			<bean>
	spring-context.jar	处理spring上下文的jar		<context>
	spring-core.jar		spring核心jar
	spring-expression.jar	spring表达式 
三方提供的日志jar
	commons-logging.jar	日志

2、编写配置文件 applicationContext.xml

实体类

实现对应的getter  and setter 方法
public class Student {
	private int stuNo ; 
	private String stuName ; 
	private int stuAge ;
	}

加入IOC容器

id:唯一标识符    class:指定类型 
<bean id="student" class="org.zq.entity.Student">
		<property name="stuNo" value="2"></property>
		<property name="stuName" value="ls"></property>
		<property name="stuAge" value="24"></property>
		 	<!-- 
		 	property:class所代表的类的属性
			name:属性名
			value:属性值
			-->
	</bean>

3、开发Spring程序(IOC)

//获取IOC容器对象
ApplicationContext conext = new ClassPathXmlApplicationContext("applicationContext.xml") ;
		//从IOC获取学生对象
		Student student = (Student)conext.getBean("student") ;

IOC容器赋值:如果是简单类型(8个基本+String),value;
如果是对象类型,ref=“需要引用的id值”,因此实现了 对象与对象之间的依赖关系
conext.getBean(需要获取的bean的id值)

实现注入(赋值)的三种方式
1.set注入:通过setXxx()赋值

默认使用的是 set方法();
依赖注入底层是通过反射实现的。
** 标签:<property…>

2.构造器注入:通过构造方法赋值

<constructor-arg value=“ls” type=“String” index=“0” name=“name”></constructor-arg>

相关属性
	index: 参数的索引位  从 0 开始(不推荐使用)
	name:参数名  (推荐使用)
	type: 参数类型
	value: 参数值
3.p命名空间注入

<bean id=“teacher” class=“org.zq.entity.Teacher” p:age=“25” p:name=“ww” ></bean>

注意:
	使用p命名空间注入时, 需要先引入p命名空间
	xmlns:p="http://www.springframework.org/schema/p"
	简单类型:
		p:属性名="属性值"
	引用类型(除了String外):
		p:属性名-ref="引用的id"
	注意多个 p赋值的时候 要有空格。
注意**
无论是String还是Int/short/long,在赋值时都是 value="值" ,
因此建议 此种情况 需要配合 name\type进行区分

给对象类型赋值null :
	<property name="name" >  
			<null/>       -->注意 没有<value>
	</property>
赋空值 ""  
	<property name="name" >  
			<value></value>  
	</property>
对集合类型赋值(array、list、set、map、properties)
都有相对应的标签
	1<list>
		 	<value>
	2<array>
			<value>
	3<set>
			<value>
	4<map>
			<entry>
				<key>
					<value>				
				<value>
5<props>
			<prop key="foot4">足球4</prop>

某些可以混着用但是不建
在这里插入图片描述

自动装配
<bean ... class="org.zq.entity.Course"  autowire="byName|byType|constructor|no" > 
	 byName本质是byId
  • byName: 自动寻找:其他bean的id值=该Course类的属性名
  • byType: 其他bean的类型(class) 是否与 该Course类的ref属性类型一致 (注意,此种方式 必须满足:当前Ioc容器中 只能有一个Bean满足条件 )
  • constructor: 其他bean的类型(class) 是否与 该Course类的构造方法参数 的类型一致;此种方式的本质就是byType
全局自动装配

可以在头文件中 一次性将该ioc容器的所有bean 统一设置成自动装配:

<beans xmlns="http://www.springframework.org/schema/beans"
...
default-autowire="byName">

自动装配虽然可以减少代码量,但是会降低程序的可读性,使用时需要谨慎

使用注解定义bean:通过注解的形式 将bean以及相应的属性值 放入ioc容器

<context:component-scan base-package="org.zq.dao">
自动装配流程
  • </context:component-scan>Spring在启动的时候,会根据base-package在 该包中扫描所有类,查找这些类是否有注解@Component(“studentDao”),如果有,则将该类 加入spring Ioc容器。
    会扫描该注解

@Component细化:

dao层注解:@Repository
service层注解:@Service
控制器层注解:@Controller
### Spring框架中IOC(控制反转)和DI(依赖注入)的概念及用法 #### 1. 控制反转 (IoC) 控制反转是一种设计模式,其核心思想是将对象的创建和依赖关系的管理从代码中分离出来,交由外部容器统一管理。这种机制可以降低组件之间的耦合度,提高系统的灵活性和可维护性。 在Spring框架中,IoC容器主要通过两个核心接口来实现:`BeanFactory` 和 `ApplicationContext`[^1]。 - **BeanFactory** 是最基本的容器,负责管理和分发Bean实例。 - **ApplicationContext** 则扩展了 `BeanFactory` 的功能,支持国际化、事件传播以及更高级的应用场景。 IoC的核心在于将对象的创建权交给容器,而不是由开发者手动完成。例如,在传统编程中,我们可能这样写: ```java UserService userService = new UserServiceImpl(); ``` 而在Spring中,可以通过配置文件或者注解的方式定义Bean,并让容器自动创建和管理它。比如使用 `@Bean` 注解: ```java @Configuration public class AppConfig { @Bean public UserService userService() { return new UserServiceImpl(); // 让Spring IoC容器管理这个对象 } } ``` 这种方式不仅简化了代码逻辑,还增强了程序的模块化程度[^2]。 --- #### 2. 依赖注入 (DI) 依赖注入是IoC的一种具体实现方式,指的是当IoC容器创建一个Bean时,会为其提供运行时所需的其他资源(即依赖)。这些资源通常是以其他Bean的形式存在。 Spring提供了多种方式进行依赖注入: - **属性注入** - **构造方法注入** - **Setter 方法注入** ##### 属性注入示例 ```java @Component public class Car { private Engine engine; @Autowired public void setEngine(Engine engine) { this.engine = engine; } public void start() { System.out.println("Car started with " + engine); } } ``` 在这个例子中,`Car` 类依赖于 `Engine` 对象,而该依赖通过 `@Autowired` 自动装配完成[^4]。 ##### 构造方法注入示例 ```java @Component public class Car { private final Engine engine; @Autowired public Car(Engine engine) { this.engine = engine; } public void start() { System.out.println("Car started with " + engine); } } ``` 这里通过构造函数完成了依赖注入,确保 `engine` 字段不可变。 ##### Setter 方法注入示例 ```java @Component public class Car { private Engine engine; @Autowired public void configure.Engine(Engine engine) { this.engine = engine; } public void start() { System.out.println("Car started with " + engine); } } ``` 无论采用哪种方式,最终目标都是为了让容器能够动态地为Bean分配所需资源,减少硬编码带来的复杂性。 --- #### 3. 实现与使用方法 为了使Spring扫描并注册带有特定注解的类作为Bean,需要确保它们位于默认扫描范围内(即启动类所在的包及其子包),否则需显式指定扫描路径。例如: ```java @SpringBootApplication @ComponentScan(basePackages = {"com.example.service", "com.example.repository"}) public class Application { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); Object beanInstance = context.getBean("someBeanName"); System.out.println(beanInstance); } } ``` 此代码片段展示了如何启动应用程序上下文,并从中获取已注册的Bean实例[^5]。 --- #### 4. 示例教程 假设我们需要构建一个简单的图书管理系统,涉及以下三个实体:`Library`, `Book`, 和 `Reader`。以下是基于Spring Boot的一个简单实现方案。 ##### 配置类 ```java @Configuration public class LibraryConfig { @Bean public Book book() { return new Book("Effective Java", "Joshua Bloch"); } @Bean public Reader reader(Book book) { return new Reader("Alice", book); } } ``` ##### 主业务逻辑 ```java @SpringBootApplication public class LibraryApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(LibraryApplication.class, args); Reader alice = context.getBean(Reader.class); alice.readBook(); } } class Reader { private String name; private Book currentBook; public Reader(String name, Book book) { this.name = name; this.currentBook = book; } public void readBook() { System.out.printf("%s is reading '%s' by %s.%n", name, currentBook.getTitle(), currentBook.getAuthor()); } } class Book { private String title; private String author; public Book(String title, String author) { this.title = title; this.author = author; } public String getTitle() { return title; } public String getAuthor() { return author; } } ``` 执行以上代码后,输出如下结果: ``` Alice is reading 'Effective Java' by Joshua Bloch. ``` 这表明依赖已经成功注入,且整个流程完全受控于Spring IoC容器[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值