在传统的 Java 应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。但在 Spring 应用中,Java 对象创建的控制权是掌握在 IoC 容器手里,开发者通过XML或注解的配置将Java对象的管理权交给IoC容器,对象的创建由Spring完成。当开发者需要用到对象时,可以直接从Spring中获取对象,不需要再自行创建。
IoC 带来的最大改变不是代码层面的,而是从思想层面上发生了“主从换位”的改变。原本开发者是主动的一方,它想要使用什么资源就会自己创建。但在 Spring 应用中,IoC 容器掌握着主动权,开发者则变成了被动的一方,等待 IoC 容器创建对象后使用。
在应用开发中,并不是所有对象都交给Spring创建,开发者经常将功能类的对象交给Spring去创建,这些类的对象创建后只需要调用功能,实现功能即可,但实体对象,因为每次创建存储的数据或代表的内容都不尽相同,所以实体类的对象还是使用常规方式(new)来实现对象创建。
DAO层
public interface IDemoDAO {
public void show();
}
public class DemoDAO implements IDemoDAO {
@Override
public void show() {
System.out.println("我是DAO方法");
}
}
Service层
public interface IDemoService {
public void show();
}
public class DemoService implements IDemoService {
private IDemoDAO demoDAO=new DemoDAO();
@Override
public void show() {
demoDAO.show();
}
}
在applicationContext.xml中添加Bean配置
<bean id="demoDAO" class="com.demo.DAO.Impl.DemoDAO">bean>
<bean id="demoService" class="com.demo.service.Impl.DemoService">bean>
获取IoC创建的对象
//创建ApplicationContext,通过实例化ClassPathXmlApplicationContext获取配置文件
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");
//getBeanDefinitionNames获取配置文件中所有加载的Bean
String[] str=applicationContext.getBeanDefinitionNames();
for (String s : str) {
System.out.println(s);
}
//getBean通过Bean的id属性获取对象
IDemoService demoService1= (IDemoService) applicationContext.getBean("demoService");
demoService1.show();
通过案例可以看到Spring通过配置,为我们创建了对象,但是目前我们遇到了问题,问题就是,我们在实现过程中,Service要引用DAO的对象进行功能实现,我们的DAO虽然交给了Spring去创建,但我们依旧需要手动创建,也就是说我们要想实现功能,在Service中就要依赖于DAO的对象实现功能,这样的形式,我们也可以交给Spring帮我们解决,这就是SpringIoC中重要的功能—依赖注入(DI)
在applicationContext.xml中进行修改
<bean id="demoDAO" class="com.demo.DAO.Impl.DemoDAO">bean>
<bean id="demoService" class="com.demo.service.Impl.DemoService">
<property name="demoDAO" ref="demoDAO"/>
bean>
Service类修改
public class DemoService implements IDemoService {
private IDemoDAO demoDAO;
public void setDemoDAO(IDemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
@Override
public void show() {
demoDAO.show();
}
}
通过配置文件实现SpringIoC,可以很好的分离代码和配置,有较高的解耦性,但操作较为繁杂,所以Spring又提供了以注解形式对IoC进行配置的方式,虽然解耦性降低,但代码实现较为轻便。
IoC核心注解:
applicationContext.xml文件配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<context:component-scan base-package="com.demo"/>
beans>
DAO层
@Repository
public class DemoDAO implements IDemoDAO {
@Override
public void show() {
System.out.println("我是DAO方法");
}
}
Service层
@Service
public class DemoService implements IDemoService {
//@Autowired
//@Qualifier("demoDAO")
@Resource
private IDemoDAO demoDAO;
/*
public void setDemoDAO(IDemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
*/
@Override
public void show() {
demoDAO.show();
}
}
获取IoC对象
//创建ApplicationContext,通过实例化ClassPathXmlApplicationContext获取配置文件
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");
//getBeanDefinitionNames获取配置文件中所有加载的Bean
String[] str=applicationContext.getBeanDefinitionNames();
for (String s : str) {
System.out.println(s);
}
//getBean通过Bean的id属性获取对象
IDemoService demoService1= (IDemoService) applicationContext.getBean("demoService");
demoService1.show();
@Autowired 和 @Resource 都是用来实现依赖注入的注解(在 Spring/Spring Boot 项目中),但二者却有着不同: