背景
我们已经学些了IOC概念和原理详情请见 一篇文章解释清楚IOC和DI
下面说如何实现IOC容器的效果。
实现
首先引入jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.0.RELEASE</version> </dependency>
xml方式
public class SpringTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) applicationContext.getBean("person"); person.eat(); } }
package IOC2023年7月1日.xml方式; public class Person { private String name;//名字 private Fruit fruit;//水果 public String getName() { return name; } public void setName(String name) { this.name = name; } public Fruit getFruit() { return fruit; } public void setFruit(Fruit fruit) { this.fruit = fruit; } //吃水果方法 public void eat(){ System.out.println(name+"吃一个"+fruit.getColor()+"的"+fruit.getName()+"觉得很"+fruit.getTaste()); } }
package IOC2023年7月1日.xml方式; public class Fruit { private String name;//水果名 private String color;//颜色 private String taste;//口味 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getTaste() { return taste; } public void setTaste(String taste) { this.taste = taste; } @Override public String toString() { return name+"的味道是"+taste+"颜色是"+color; } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--使用bena标签创建对象:创建Fruit的对象在spring中的标记为fruit。我们可以通过fruit找到该对象并使用 id属性:可以随便写。spring创建对象存储在spring中容器中的名字,注意不是对象名 class属性:创建的对象的全路径 --> <bean id="fruit" class="IOC2023年7月1日.xml方式.Fruit"> <!--使用property标签赋值 name属性:类中的属性名 value属性:具体的数据 --> <property name="name" value="banana"></property> <property name="color" value="yellow"></property> <property name="taste" value="sweet"></property> </bean> <!--创建另外一个Fruit对象--> <bean id="fruit2" class="IOC2023年7月1日.xml方式.Fruit"> <property name="name" value="苹果"></property> <property name="color" value="绿"></property> <property name="taste" value="酸"></property> </bean> <!--创建Person对象--> <bean id="person" class="IOC2023年7月1日.xml方式.Person"> <!--使用ref属性引用IOC容器中的对象进行赋值--> <property name="fruit" ref="fruit"></property> <property name="name" value="小明"></property> </bean> </beans>
是 Spring 配置文件的根节点。
用来定义一个 JavaBean。id 属性是它的标识,在文件中必须唯一;class 属性是它关联的类。
实现结果:
使用配置文件:
配置文件通常以特定格式(如XML、JSON、YAML等)编写。
配置文件包含了应用程序的各种配置参数。
配置文件的修改可以改变应用程序的行为和属性。
配置文件的结构化格式易于组织和维护。
配置文件相对灵活,允许在不重新编译和部署应用程序的情况下进行调整。
使用注解:
注解是一种特殊的注释形式,提供了额外的元数据信息。
注解通过在代码中标记和配置应用程序的组件和属性。
注解以声明式的方式提供配置信息,使得配置更直观易懂。
注解通常在编译时或运行时通过注解处理器解析和处理。
注解可以在编译阶段或运行阶段进行验证、转换和处理。
注意事项:
配置文件适用于相对复杂或动态的配置信息,而注解更适合直观和紧密集成的配置管理。
配置文件的修改通常需要手动编辑,而注解可以直接在代码中配置。
注解的使用需要遵循特定的注解规范和语法,需要适应和学习。
过度使用注解可能导致代码的可读性和维护性下降,需要谨慎使用和设计注解。
注解方式
package IOC2023年7月1日.Annotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.ClassPathXmlApplicationContext; import javax.annotation.Resource; public class SpringTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext1.xml"); Person person = (Person) applicationContext.getBean("person"); person.eat(); } }
package IOC2023年7月1日.Annotation; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.Resource; @Component public class Person { @Value("小明") private String name;//名字 //使用Resource注解引用IOC容器中的对象给属性赋值 @Resource(name = "fruit") private Fruit fruit;//水果 public String getName() { return name; } public void setName(String name) { this.name = name; } public Fruit getFruit() { return fruit; } public void setFruit(Fruit fruit) { this.fruit = fruit; } //吃水果方法 public void eat(){ System.out.println(name+"吃一个"+fruit.getColor()+"的"+fruit.getName()+"觉得很"+fruit.getTaste()); } }
package IOC2023年7月1日.Annotation; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * ClassName: Fruit * 使用@Component注解创建对象,相当于bean标签,value属性相当于id属性 * 意思是创建Fruit类的对象存储在IOC容器中,在IOC中名字为fruit * 使用Value注解来为属性注入固定的值 */ @Component(value = "fruit") public class Fruit { @Value("芒果") private String name;//水果名 @Value("黄色") private String color;//颜色 @Value("芒果味") private String taste;//口味 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getTaste() { return taste; } public void setTaste(String taste) { this.taste = taste; } @Override public String toString() { return name+"的味道是"+taste+"颜色是"+color; } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--开启包扫描,可以扫描到com.stt包下的所有注解--> <context:component-scan base-package="IOC2023年7月1日.Annotation"/> </beans>
实现效果:
升华
注解方式的好处:
简洁明了:通过在代码中添加注解,可以直观地标识出哪些类需要进行依赖注入,使代码结构更加清晰和易于理解。
编译时检查:注解方式在编译时就可以进行类型检查和错误检查,可以及早发现依赖注入相关的问题,减少运行时错误。
便于维护:通过注解方式进行依赖注入,可以方便地修改和调整注入的依赖关系,而无需修改繁琐的配置文件。
注解方式的坏处:
紧耦合:使用注解进行依赖注入可能会导致代码和框架之间的紧耦合,使得代码依赖于特定的注解和框架。
难以配置复杂依赖:对于复杂的依赖关系,使用注解方式可能会变得复杂和难以配置,可能需要编写大量的注解和参数配置。
配置文件方式的好处:
灵活可配置:通过配置文件可以灵活地配置依赖关系,可以在运行时动态修改和调整依赖关系,无需重新编译代码。
解耦合:配置文件方式可以将依赖关系从代码中分离出来,降低了代码的耦合度,使得代码更加可维护和可扩展。
支持复杂依赖:配置文件方式可以支持更复杂的依赖关系,可以配置各种类型的依赖注入和依赖解析策略。
配置文件方式的坏处:
配置复杂:相比注解方式,配置文件方式可能需要编写更多的配置信息,配置文件的编写和维护可能会增加开发的工作量。
运行时错误:由于配置文件是在运行时加载和解析的,因此配置错误或格式错误可能会导致运行时错误,增加调试和排查问题的难度。
综上所述,注解方式和配置文件方式都有自己的适用场景和优劣势,具体选择哪种方式取决于项目的需求、团队的偏好和开发的复杂度。一般而言,注解方式适合简单的依赖注入场景,而配置文件方式适合复杂的依赖注入和需要灵活配置的场景。