IoC(Inversion of Control,控制反转)容器是Spring框架中非常 重要的核心组件,可以说它是伴随Spring的诞生和成长的组件。Spring通过IoC容器来管理所有的Java对象(也称bean)及其相互间的依赖关系。
1 依赖注入和控制反转
依赖注入(Dependency Injection)是对“控制反转”的不同说法,本质是一回事。
2 IoC容器和bean
Spring通过IoC容器来管理所有Java对象及其相互之间的依赖关系。
IoC容器在创建bean的时候,会注入其依赖项。
IoC的应用有以下两种设计模式:
- 反射:在运行状态中,根据提供的类的路径或类名,通过反射来动态获取该类的所有属性和方法。
- 工厂模式:把IoC容器当做一个工厂,在配置文件或注解中给出定义,然后利用反射技术,根据给出的类名生成相应的对象。对象生成的代码及对象之间的依赖关系在配置文件中定义,实现了解耦。
Spring IoC容器的核心基础包:
- org.springframework.beans
- org.springframework.context
3 配置和使用
配置方式有:
- xml形式
<bean id = "..." class="...">
<!-- 放置这个bean的协作者和配置 -->
</bean>
- 注解形式
@Configuration
public class AppConfig{
@Bean
public MyService myService(){
return new MyServiceImpl();
}
}
4 注入方式
- 构造器注入
- setter注入
5 实战:依赖注入的例子
- 消息服务接口和实现类
public interface MessageService {
String getMessage();
}
public class MessageServiceImpl implements MessageService {
private String username;
private int age;
public MessageServiceImpl(String username, int age) {
this.username = username;
this.age = age;
}
@Override
public String getMessage() {
return "Hello World!" + "\nusername is " + username + ",age is " + age;
}
}
- 打印器类
public class MessagePrinter {
final private MessageService messageService;
public MessagePrinter(MessageService messageService) {
this.messageService = messageService;
}
public void printMessage() {
System.out.println(this.messageService.getMessage());
}
}
- 配置文件
<!--定义bean,并使用构造器注入-->
<bean id="messageServiceImpl" class="com.spring.quickstart.MessageServiceImpl">
<constructor-arg name="username" value="Tom"/>
<constructor-arg name="age" value="20"/>
</bean>
<bean id="messagePrinter" class="com.spring.quickstart.MessagePrinter">
<constructor-arg name="messageService" ref="messageServiceImpl"/>
</bean>
- 应用主类
public class MessageApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
MessagePrinter messagePrinter = context.getBean(MessagePrinter.class);
messagePrinter.printMessage();
}
}
- 运行结果
6 依赖注入详细配置
- 直接赋值
- 引用其他bean
- 内部bean
- 集合
- Null及空字符的值
- xml短域名空间
- 复合属性名称
7 IoC综合练习:Boss、Car、Meeting
Car:属性有brand、color、parameter
Boss:属性有name、company、car、hobbies
Meeting:属性theme、bosses
综合采用所学内容,设计并完成以上综合练习Car类
public class Car {
private String brand;
private String color;
private String parameter;
public Car(String brand, String color, String parameter) {
this.brand = brand;
this.color = color;
this.parameter = parameter;
}
public Car() {
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getParameter() {
return parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", color='" + color + '\'' +
", parameter='" + parameter + '\'' +
'}';
}
}
- Boss类
public class Boss {
private String name;
private String Company;
private Car car;
private List<String> hobbies;
public Boss(String name, String company, Car car, List<String> hobbies) {
this.name = name;
Company = company;
this.car = car;
this.hobbies = hobbies;
}
public Boss() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCompany() {
return Company;
}
public void setCompany(String company) {
Company = company;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
@Override
public String toString() {
return "Boss{" +
"name='" + name + '\'' +
", Company='" + Company + '\'' +
", car=" + car +
", hobbies=" + hobbies +
'}';
}
}
- Meeting类
public class Meeting {
private String theme;
private List<Boss> bosses;
public Meeting(String theme, List<Boss> bosses) {
this.theme = theme;
this.bosses = bosses;
}
public Meeting() {
}
public String getTheme() {
return theme;
}
public void setTheme(String theme) {
this.theme = theme;
}
public List<Boss> getBosses() {
return bosses;
}
public void setBosses(List<Boss> bosses) {
this.bosses = bosses;
}
@Override
public String toString() {
return "Meeting{" +
"theme='" + theme + '\'' +
", bosses=" + bosses +
'}';
}
}
- 配置文件
<!--配置三个Car的bean-->
<bean id="car1" class="com.spring.ioc.Car">
<constructor-arg name="brand" value="奔驰"/>
<constructor-arg name="color" value="黑色"/>
<constructor-arg name="parameter" value="4.0T"/>
</bean>
<bean id="car2" class="com.spring.ioc.Car">
<constructor-arg name="brand" value="宝马X6"/>
<constructor-arg name="color" value="白色"/>
<constructor-arg name="parameter" value="3.8T"/>
</bean>
<bean id="car3" class="com.spring.ioc.Car">
<property name="brand" value="劳斯莱斯"/>
<property name="color" value="金色"/>
<property name="parameter" value="4.5T"/>
</bean>
<!--配置三个Boss的bean-->
<bean id="boss1" class="com.spring.ioc.Boss">
<constructor-arg name="name" value="马云"/>
<constructor-arg name="company" value="阿里巴巴"/>
<constructor-arg name="car" ref="car1"/>
<constructor-arg name="hobbies">
<list>
<value>演讲</value>
<value>写作</value>
</list>
</constructor-arg>
</bean>
<bean id="boss2" class="com.spring.ioc.Boss">
<property name="name" value="马化腾"/>
<property name="company" value="腾讯"/>
<property name="car" ref="car2"/>
<property name="hobbies">
<list>
<value>打游戏</value>
<value>看电影</value>
</list>
</property>
</bean>
<bean id="boss3" class="com.spring.ioc.Boss">
<property name="name" value="李彦宏"/>
<property name="company" value="百度"/>
<property name="car" ref="car3"/>
<property name="hobbies">
<list>
<value>阅读</value>
<value>运动</value>
</list>
</property>
</bean>
<!--配置一个Meeting的bean-->
<bean id="meeting" class="com.spring.ioc.Meeting">
<property name="theme" value="2019互联网高层峰会"/>
<property name="bosses">
<list>
<ref bean="boss1"/>
<ref bean="boss2"/>
<ref bean="boss3"/>
</list>
</property>
</bean>
- MeetingApp主类
public class MeetingApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
Meeting meeting = context.getBean(Meeting.class);
System.out.println(meeting);
}
}
- 运行结果
Meeting{theme='2019互联网高层峰会', bosses=[Boss{name='马云', Company='阿里巴巴', car=Car{brand='奔驰', color='黑色', parameter='4.0T'}, hobbies=[演讲, 写作]}, Boss{name='马化腾', Company='腾讯', car=Car{brand='宝马X6', color='白色', parameter='3.8T'}, hobbies=[打游戏, 看电影]}, Boss{name='李彦宏', Company='百度', car=Car{brand='劳斯莱斯', color='金色', parameter='4.5T'}, hobbies=[阅读, 运动]}]}