自学笔记,如有错误请指出,我虚心改正
环境说明:Windows10、MyEclipse2016ci、jdk1.8、MySQL5.7、Tomcat9.0
目录
SpringIoC的基本概念
SpringIoC容器
BeanFactory
ApplicationContext
1、通过ClassPathXmlApplicationContext创建
2、通过FileSystemXmlApplicationContext创建
3、通过Web服务器实例化ApplicationContext容器
依赖注入的类型
使用构造方法注入
创建dao包
创建service包
编写配置文件
创建test包
使用属性的setter方法注入
创建DIServiceImlps
将DIServiceImpls类托管给Spring
在test中测试setter方法注入
上回提到了Spring IoC的工作机制,究竟何为IoC?如何理解IoC?IoC有何优势?
IoC即Inversion of Control “控制反转”是Spring的基础,简单的理解是把“创建对象的权利”交由Spring,仅用语言很难形容,我参考知乎用户Mingqi的回答来帮助理解,SSM——Spring(番外2)——IoC形象理解(转自知乎Mingqi的回答)(https://blog.csdn.net/jinxlzc/article/details/88526660)
Spring提供了两种类型的IoC容器的实现:
1、BeanFactory:IoC容器的基本实现,它是一个管理Bean 的工厂,主要负责初始化各种Bean
2、ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口
下面我分别用以上两种类型IoC容器实现一下
在创建BeanFactory实例时需要提供XML文件的绝对路径,现在我就在上次做的SpringDemo1中修改实现,将Text.Text.java做如下修改
package Test;
import dao.TestDao;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
/**
* @author lzc
*
*/
public class Test {
public static void main(String[] args) {
BeanFactory beanfact=new XmlBeanFactory(new FileSystemResource("C:\\Users\\64522\\Workspaces\\MyEclipse 2016 CI\\SpringDome1\\src\\applicationContext.xml"));
TestDao td=(TestDao)beanfact.getBean("test");
td.say();
}
}
然而,BeanFactory类已被最新的Spring废弃掉,证据就是下图
所以另一种方式即ApplicationContext是现在最主流,也是我们最常用的方式
刚才提到,ApplicationContext是BeanFactory的子接口,ApplicationContext接口除了包含BeanFactory的所有功能外还提供了对国际化、资源访问、事件传播等内容的支持
创建ApplicationContext接口实例的通常一下有3种方法:
即相对路径创建,将src下的xml使用通过ClassPathXmlApplicationContext进行指定,这种方法是最常用,也是之前Spring(1)中使用的方法,并且还是我人最喜欢的一种方法,具体实现在应用层的代码如下:
package Test;
import dao.TestDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author lzc
*
*/
public class Test {
public static void main(String[] args) {
ApplicationContext appCon =new ClassPathXmlApplicationContext("applicationContext.xml");
TestDao thetest=(TestDao)appCon.getBean("test");
thetest.say();
}
}
即相绝对路径创建,使用FileSystemXmlApplicationContext指定某一路径下 的xml配置文件,这里我把原项目中的xml右键属性复制绝对路径,不要忘了把"\"改为"\\",具体实现在应用层的代码如下:
package Test;
import dao.TestDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* @author lzc
*
*/
public class Test {
public static void main(String[] args) {
ApplicationContext appCon=new FileSystemXmlApplicationContext("C:\\Users\\64522\\Workspaces\\MyEclipse 2016 CI\\SpringDome1\\src\\applicationContext.xml");
TestDao thetest=(TestDao)appCon.getBean("test");
thetest.say();
}
}
在Web服务器实例化ApplicationContext容器时,一般基于org.springframework.web.context.ContextLoaderListener的方式实现,需要将spring-web-5.1.5.RELEASE.jar导入项目中,然后在项目的web.xml中配置如下代码,其中context-param标签中内容是为了加载src目录下classpath:applcationContext.xml文件,listener标签中内容是为了指定以ContextLoaderListener方式启动Spring容器
contextConfigLocation
classpath:applcationContext.xml
org.springframework.web.context.ContextLoaderListener
在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象注入Bean组件中。Spring实现依赖注入的常用方式有两种,一种是使用构造方法注入,另一种是使用属性的setter方法注入
Spring框架可以采用Java的反射机制,通过构造方法完成依赖注入。下面新建一个SpringDemo2项目实现构造方法注入的过程,SpringDemo2的结构与使用的包与SpringDemo1相同
在SpringDemo2项目中创建dao包,并在该包中创建DIDao接口和接口实现类DIDaoImpl,创建dao包的目的是在service中使用构造方法依赖注入DIDao接口对象
DIDao代码:
package dao;
/**
* @author lzc
*
*/
public interface DIDao {
public void say();
}
DIDaoImpl代码:
package dao;
/**
* @author lzc
*
*/
public class DIDaoImpl implements DIDao{
@Override
public void say() {
System.out.println("DIDao say:Hello");
}
}
在SpringDemo2项目中创建service包,并在该包中创建DIService接口和接口的实现类DIServiceImpl,在DIServiceImpl中使用构造方法依赖注入DIDao接口对象
DIService代码:
package service;
/**
* @author lzc
*
*/
public interface DIService {
public void say();
}
DIServiceImpl代码:
package service;
import dao.DIDao;
/**
* @author lzc
*
*/
public class DIServiceImpl implements DIService{
private DIDao diDao;
public DIServiceImpl(DIDao diDao)
{
super();
this.diDao=diDao;
}
@Override
public void say()
{
diDao.say();
System.out.println("DIService构造方法注入say:Hello");
}
}
在src下创建Spring的配置文件applicationContext.xml,在配置文件中将dao.DIDaolmpl类托管给Spring,然后将service.DIServiceImpl类托管给Spring,让Spring创建其对象,同时给构造方法传递实参。
配置文件代码:
第一个bean标签将制定类DIDaoImpl配置给Spring让Spring创建其实例
第二个bean标签使用构造方法注入,将myDIDao注入到DIServiceImpl类的属性diDao上
constructor-arg元素用于定义类构造方法的参数,index用于定义参数的位置,ref指定某个实例的引用如果参数是常量值,ref由value代替
在项目中创建test包,并在包中创建测试类TestDI
TestDI代码如下:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.DIService;
/**
* @author lzc
*
*/
public class TestDI {
public static void main(String[] args) {
ApplicationContext appCon=new ClassPathXmlApplicationContext("applicationContext.xml");
DIService ds=(DIService)appCon.getBean("DIService");
ds.say();
}
}
运行结果如下:
setter方法注入是利用JavaBean规范所定义的setter方法来完成注入,对于setter方法注入,Spring框架也是使用Java 的反射机制实现的,现在将刚才的SpringDemo2中实现setter方法注入
在service包下建用来测试setter方法注入的DIService接口实现类DIServiceImlps,在DIServiceImlps类中使用属性的setter方法依赖注入DIDao接口对象
DIServiceImlps代码如下:
package service;
import dao.DIDao;
/**
* @author lzc
*
*/
public class DIServiceImpls implements DIService{
private DIDao diDao;
public void setDiDao(DIDao diDao) {
this.diDao = diDao;
}
@Override
public void say()
{
diDao.say();
System.out.println("DIService setter方法注入say:Hello");
}
}
将DIServiceImpls类托管给Spring,让Spring创建其对象,同时调用DIServiceImpls类的setter方法完成依赖注入
在配置文件中添加如下代码:
调用DIServiceImpls类的setter方法,将myDIDao注入到DIServiceImpls类的属性diDao上
在测试类的主方法中通过容器获取DIServices实例,测试setter方法注入
在测试类添加如下代码
DIService dss=(DIService)appCon.getBean("DIServices");
dss.say();
运行结果如下:
项目的完整结构如下: