降低程序间的依赖关系,如果我们自己写代码,降低的方式是用工厂模式来实现,BeanFactory类这段代码并没有难度,如果在实际开发中我们自己来写的话,肯定会消耗更多的精力,所以我们把这一段内容完全交给了spring,使用spring中的IOC降低程序间的依赖关系,即解耦。
控制反转IOC:把创建对象的权利交给框架。实现类已经创建好了,只是把创建对象的工作交给spring而已。
下面先创建实现类AccountServiceImpl和AccountDaoImpl:
1、 创建maven的jar工程,打包方式为jar包
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.itheima</groupId> <artifactId>day01_eesy_03spring</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> </project>
2、 编写业务层接口:
public interface IAccountService { /** * 模拟保存账户 */ void saveAccount(); }
3、 编写业务层实现类,业务层调用持久层
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void saveAccount(){
accountDao.saveAccount();
}
}
如果没有编写任何构造方法,那么编译器会默认赠送一个构造方法,没有参数,方法体什么事都不做。
4、 编写持久层接口:
public interface IAccountDao { /** * 模拟保存账户 */ void saveAccount(); }
5、 编写持久层实现类:
public class AccountDaoImpl implements IAccountDao { public void saveAccount(){ System.out.println("保存了账户"); } }
spring框架完成创建对象工作,我们看看使用spring框架后能不能将实现类创建成对象。
6、添加Spring的maven坐标:spring-context
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies>
这样依赖中就会出现如下jar包:
Spring核心容器索要用到的5个jar包:context、 aop、beans、core、jcl
Spring-aop是基于注解的开发的必备jar包,由于spring在导坐标的时候不知道你使用XML还是用注解,所以把你可能用到的jar包都关联进来了。
Spring-jcl:spring把Apache的日志组件commons-loggin-1.2.jar集成进来做成了自己的一个jar包。
7、在resources目录下创建bean.xml文件,
bean这个名字可以自定义,只要不是中文。
<?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"> <!--把对象的创建交给spring来管理--> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean> </beans>
在bean.xml文件中进行配置,把对象的创建交给spring来管理,用bean标签,该标签有两属性:id(你获取对象时的唯一标识),class(全限定类名)
实现类AccountServiceImpl和AccountDaoImpl已经创建好了,只是把创建对象的工作交给spring而已。
8、下面来证明spring已经根据实现类来创建对象。代码如下:
public class Client { public static void main(String[] args) { //1.获取核心容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");//2.根据id获取Bean对象 IAccountService as = (IAccountService)ac.getBean("accountService"); IAccountDao accountDao = ac.getBean("accountDao",IAccountDao.class); System.out.println(as); System.out.println(accountDao); } }
获取spring创建好的IOC核心容器对象ApplicationContext。
参数为配置文件bean.xml的位置,由于是放在类路径resources目录下,所以直接写就可以了,
ApplicationContext的基于xml配置的实现类有两个:ClassPathXMLApplicationContext和FileSystemXMLApplicationContext,基于注解配置的实现类:AnnotationConfigApplicationContext
根据唯一标识id获取对象。
这两种方式获取对象都可以,一种是拿到object对象,然后进行强转,一种是传递一个字节码,让它按照字节码进行强转得到我们想要的对象。
打印结果如下:
读取配置文件,反射创建对象并存入map中的过程全部让spring干了,我们需要做的是创建配置文件,把配置信息交给spring,然后得到核心容器,再根据唯一标识取出对象就可以了。
改造成基于XML的IOC配置:
1、在AccountServiceImpl实现类中添加set方法
public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao; public AccountServiceImpl(){ System.out.println("对象创建了"); } public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } public void saveAccount(){ accountDao.saveAccount(); } }
2、在bean.xml中注入依赖
<?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"> <!--把对象的创建交给spring来管理--> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean> </beans>
3、测试:
public class Client { public static void main(String[] args) { //1.获取核心容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");//2.根据id获取Bean对象 IAccountService as = (IAccountService)ac.getBean("accountService"); IAccountDao accountDao = ac.getBean("accountDao",IAccountDao.class); System.out.println(as); System.out.println(accountDao); as.saveAccount(); } }
结果: