欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring IOC

程序员文章站 2022-07-12 13:58:34
...

前言

我们在实现类和类之间的依赖的时候,通常需要new需要被调用的类。

比如;Service层 New 了一个Dao层的类, 可以考虑用工厂,利用factroy来得到dao层的具体实现类,但工厂模式的缺陷只能创建一个对象,这个时候可以考虑使用抽象工厂,可以创建多个对象。

spring用IOC来做这个事情,spring容器来定位对象,创建好后提供可使用的对象,并且还可以管理对象和对象之间的依赖关系。

先看一下工厂模式。

工厂模式

隐藏了具体创建ItemDao4OracleImpl的过程,在Service层调用的时候,直接找相应的类创建工厂就可以实现。

但是如果想要修改成Mysql的数据库,Service就需要对代码进行修改,因为当初是直接New 的具体的创建Oracle的工厂类,这就违背了对修改关闭,对拓展开发的原则。

这个时候可以通过反射来实现。

Spring IOC

反射调用:

用反射来代替普通的new调用工厂类

把工厂类配置到xml文件中,通过读取xml文件,后获取类交给反射工厂进行实例化,如果修改只修改配置文件即可,如图:

Spring IOC

 会发现这样也省去了new具体的类,变的更灵活可配,只要给反射工厂传入你需要调用类名,就可以实现调用,给你实例化好,不需要我们进行实例化。

那可不可以让不同层的类和类之间的调用都采用这样的方式。也就是实现创建多个类。

抽象工厂

可以通过一个中间的工厂,把需要实例化的类都交给它,它可以根据需要创建多个类

Spring IOC

 
/**

* 抽象工厂,主要创建两个系列的产品:

*   1、Manager系列

*   2、Dao系列产品

* @author Administrator

*

*/

public class BeanFactory {


   /*单例模式*/

   private static BeanFactory instance = new BeanFactory();

   public static BeanFactory getInstance() {

      return instance;

   }


   private final String beansConfigFile = "beans-config.xml";

   
   //保存Service相关对象

   private Map serviceMap = new HashMap();

   

   //保存Dao相关对象

   private Map daoMap = new HashMap();



   //存储 文件中的值

   private Document doc;


   /*获取到xml文件中的内容存储到document中*/

   private BeanFactory() {

      try {

         doc = new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));

      } catch (DocumentException e) {

         e.printStackTrace();

         throw new RuntimeException();

      }

   }

 

   /**

    * 根据产品编号取得Service系列产品

    * @param

    * @return

    */

   public synchronized Object getServiceObject(Class c){

      return "省略--service和getDaoObject一样";

   }



   /**

    * 根据产品编号取得Service系列产品

    * @param

    * @return

    */

   public synchronized Object getDaoObject(Class c){

      //如果存在相关对象实例,返回

      if (daoMap.containsKey(c.getName())) {

         return daoMap.get(c.getName());

      }

      // 如果没有实例化过,----取出传入的类名----对应doc中的id----找到class----反射进行实例化----存入map

      Element beanElt = (Element)doc.selectSingleNode("//dao[@id=\\\"\" + c.getName() + \"\\\"]");

      String className = beanElt.attributeValue("class");

      Object dao = null;

      try {

         dao = Class.forName(className).newInstance();

         //将创建好多的对象放到Map中

         daoMap.put(c.getName(), dao);

      } catch (Exception e) {

         throw new RuntimeException();

      }

      return dao;

   }

}

 

Spring IOC

spring框架把类似这样的思想的代码整合起来,专门去做了这样的封装,来实现管理对象的目的。我们只需通过使用spring的配置文件applicationContext.xml来实现它提供的服务。

使用方式有两种:

第一种:不使用注解:

在applicationContext.xml中,每个bean标签都相当于注入springIOC容器中的类

在代码中UserManageImpl是需要调用dao层下userDao4Oracle类下的方法,也就是userManage依赖于userDao4Oracle,

如下,可以直接在<bean id="userManager" class="com.bjpowernode.spring.manager.UserManagerImpl"></bean>中注入<constructor-arg ref="usrDao4Oracle"/>来表示他们的依赖关系。

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
  
  <bean id="userDao4Mysql" class="com.bjpowernode.spring.dao.UserDao4MySqlImpl"/>
  
  <bean id="usrDao4Oracle" class="com.bjpowernode.spring.dao.UserDao4OracleImpl"/>
  
  <bean id="userManager" class="com.bjpowernode.spring.manager.UserManagerImpl">
       <!--
       <constructor-arg ref="userDao4Mysql"/>
        -->
       
       <constructor-arg ref="usrDao4Oracle"/>
        
       <!-- <property name="userDao" ref="usrDao4Oracle"/>-->
  </bean>
</beans>

在代码中:可以不去new UserDao ,就可以直接调用userDao.addUser(~,~)

PS:另外看代码中的注释,可以通过另一种方式,实现注入。和xml文件中的配置相互匹配即可。

public class UserManagerImpl implements UserManager {
   // 使用spring已经实例化好并注入的userDao
   private UserDao userDao;
   public UserManagerImpl(UserDao userDao) {
   this.userDao = userDao;
}
   public void addUser(String username, String password) {
      userDao.addUser(username, password);
   }
   /*如果xml不采用constructor-arg构造方法注入,
   需要配置文件中写<property name="userDao" ref="usrDao4Oracle"/>
   可以采用set来注入
   public void setUserDao(UserDao userDao) {
      this.userDao = userDao;
   }
   */

}

第二种方式:使用注解的方式:

在applicationContext.xml中配置如下内容

<!-- 注解式的配置 -->
<context:annotation-config/>
<!-- 自动扫描与装配bean文件夹dao,service等 -->
<context:component-scan base-package="base,dao,domain,service,service.impl,util,view.action"></context:component-scan>

在代码中:表示service层和dao层间的依赖关系,使用@Resource注解 注入dao层

@Service:在Service层中使用

@Transactional:表示事物管理(不详细做介绍)

@Service
@Transactional
public class RolerServiceImpl implements RoleService {
    @Resource
    RoleDao roleDao;
 // 此处省略若干逻辑代码
}

常见的注解还有:

实例化的注解列表:

@Compoent :应用于普通的类中

@Service:在servie层中使用

@Controller:标记controller层

@Reposistory:在dao层中使用

@Resource:根据设置的明朝名称来进行注入

 

注入的注解的标签:

@Autowired:自动注入的方式进行注入,默认根据类的名称来进行装配

@Resource(name="")没有name时3和autowired一样但是他可以根据名称进行装配

装配标签:在xml里面的

等等~

小结:还在学习中,请多指教,如果对你有用请点个赞吧~

相关标签: ——框架 spring