在开始接触Spring之前来先看看之前写的代码
这是IUserService接口里面的方法:
public interface IUserService {
void saveAccount();
}
然后是接口的实现类:
public class IUServicesImpl implements IUserService {
private IUserDao userDao = new IUserDaoImpl();
@Override
public void saveAccount() {
userDao.saveAccount();
}
}
接着是操作数据库层的Dao
public interface IUserDao {
void saveAccount();
}
接着就是接口的实现类
public class IUserDaoImpl implements IUserDao {
@Override
public void saveAccount() {
System.out.println("保存用户了......");
}
}
然后我们来测试代码:
public class AppTest{
@Test
public void testSpring(){
IUserService userService = new IUServicesImpl();
userService.saveAccount();
}
}
通过一系列的代码我们可以发现当需要对象的时候我们需要new
这样造成的结果就是代码之间的耦合度很高,不利于代码维护
我们需要利用学习的反射知识让反射帮助我们创建对象
这样代码之间耦合稍微降低一些那么如何利用反射创建对象,这时候需要我们创建一个BeanFactory工厂类,此类的作用就是在该类中创建我们需要的对象,不在需要我们new对象只要需要传入我们类的名字就可以
第一步:
利用配置文件把我们需要的都类的实现都放在配置文件里面bean.properties
accountService=com.beijing.service.Impl.IUServicesImpl
accountDao=com.beijing.dao.Impl.IUserDaoImpl
第二部我们需要在BeanFactory中读取配置文件:
/**
* BeanFactory用来创建对象
* 配置文件
* 读物配置文件反射创建对象
*/
public class BeanFactory {
private static Properties prop;
static{
try{
prop = new Properties();
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
prop.load(resourceAsStream);
}catch (Exception e){
e.printStackTrace();
System.out.println("加载配置文件失败");
}
}
//定义一个获取new对象的方法
public static Object getBean(String benaName){
Object bean = null;
try{
String beanPath = prop.getProperty(benaName);
//System.out.println(beanPath);
bean = Class.forName(beanPath).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return bean;
}
}
这样我们需要在测试的时候需要传入一个String beanName就可以通过反射获取我们需要的对象
在我们需要new对象的地方就利用BeanFactory来创建我们需要的对象
public class IUServicesImpl implements IUserService {
//利用反射创建对象
private IUserDao userDao = (IUserDao) BeanFactory.getBean("accountDao");
@Override
public void saveAccount() {
userDao.saveAccount();
}
}
在测试类中:
public class AppTest{
@Test
public void testSpring(){
IUserService userService = (IUserService) BeanFactory.getBean("accountService");
userService.saveAccount();
}
}
到这里我们发现代码之间的耦合度降低了,但是代码之间问题还是很多
这里我们需要IUserService是单例的但是我们通过代码发现这里方式获取的是userService是多例也就是我们每次创建都会new一个新的对象
我们可以创建一个容器用来保存我们的对象
这时候修改BeanFactory工厂类
public class BeanFactory {
private static Properties prop;
//定义一个map用来保存我们要创建的对象我们称之为容器
private static Map<String,Object> beans;
static{
try{
prop = new Properties();
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
prop.load(resourceAsStream);
//实例化容器
beans = new HashMap<>();
//获取加载配置文件里面的值
Enumeration<Object> keys = prop.keys();
//遍历枚举获取里面的每个key
while (keys.hasMoreElements()){
//获取每个key
String key = keys.nextElement().toString();
//根据key获取value
String beanPath = prop.getProperty(key);
//反射创建对象
Object value = Class.forName(beanPath).newInstance();
//放入容器
beans.put(key,value);
}
}catch (Exception e){
e.printStackTrace();
System.out.println("加载配置文件失败");
}
}
/**
* 获取对象
* @param benaName
* @return
*/
public static Object getBean(String benaName){
return beans.get(benaName);
}
}
这时候在测试就会发现:
public class AppTest{
@Test
public void testSpring(){
for (int i = 0; i < 5; i++) {
IUserService userService = (IUserService) BeanFactory.getBean("accountService");
System.out.println(userService);
userService.saveAccount();
}
}
}
这里的控制台就会发现userService是单例
分析什么是控制反转(IOC)
private IUserDao userDao = new IUserDaoImpl();
private IUserDao userDao = (IUserDao) BeanFactory.getBean("accountDao");
这里是IUserService类里面需要创建的userDao对象
第一行代码知道我们创建的类的真实对象,也知道类创建是不是我们所需要的!
而第二行代码把创建对象的的权利交给BeanFactory,同时我们也不知道创建的类是否为类所用,只需要传入字符串就可以获取对象
这样的做法就是消减类与类之间的耦合性
IOC:就是把创建对象的权利交给Spring框架
Spring只能解决依赖关系,不能增删改查!