Spring学习(三)ioc工厂bean深入理解

我所理解的工厂bean:

我们在使用ioc容器形成类之间的依赖关系,也就是在配置文件中配置bean的时候,一般是class指向的是实体bean类,通过ref将另外一个bean对象注入到这个类中。如下图示:

这里写图片描述


这里圆圈里面的就是一个类,所以这个id为action的bean对象可以直接通过ref注入别的类中。然而当我们要注入一个接口,这个接口没有实现类的时候就不能这样操作了。因为无法实例化一个对象。这时我们就要采用工厂bean。像图中所示(整个例子下文有),要将UserDaoIf这个接口注入到LoginAction中,我们让DaoFactoryBean实现FactoryBean接口,这个类就会自动调用getObject()方法,返回我们需要的UserDaoIf实例,这时就可以注入到action里面了。
所以,工厂bean解决了ioc容器无法直接实例化某个对象的问题。

一、ioc工厂配置的bean分类:

划分依据:
getBean("xx") 调用某个bean对象返回的对象实例类型是否是class属性指向的类型

1、普通bean
getBean("xxx")  ==  class 属性

2、工厂bean

getBean("xxx")  !=  class属性  (class属性中指向的是一个工厂类,调用这个bean对象,想要的并不是class属性指向的工厂 ,而是该工厂负责创建的实例对象。)

二、工厂bean的必要性:

 ioc并不是万能的,并不能创建开发过程中涉及到的所有对象,当ioc无法或者不能直接实例化某个对象时,需要一个第三方工厂帮助其实例化该对象,将这个第三方工厂配置在ioc环境下,实现 ioc直接管理的对象(普通对象)  和  第三方工厂创建的对象(ioc无法直接实例的对象)  之间的依赖关系。

  ioc无法实例化什么对象? 
接口类型对象 并且本工程中不允许提供接口的实现类。(因为ioc通过反射机制创建对象,接口不能反射)比如QQ授权登录只提供验证接口、获取天气等

三、在ioc中配置工厂bean的三种方式:

1  静态工厂
2  动态工厂(忽略)
3  实现FactoryBean接口(spring提供的工厂bean根接口)
下面,通过这个例子 来了解1 、 3这两种方式:
applicationContext.xml:

<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-3.2.xsd">
    <!-- 
        使用ioc依赖注入实现LoginAction、UserDaoIf依赖关系

     -->
     <bean id="action" class="com.etoak.action.LoginAction">
        <!-- <property name="dao" ref="fb"></property> -->
        <property name="dao" ref="factory"></property>
     </bean>
     <!-- 
                1 静态工厂 ~ 工厂模式
            factory-method : 指向工厂类中提供的静态方法
                a  ioc容器会将具备改属性的bean当作工厂bean对待
                b  调用这个工厂bean时,返回的对象实例不在是class属性指向的对象类型
                    而是该工厂自动调用factory-method属性指向的方法(必须是静态的)返回的对象类型
                    所以这里getBean()得到的是UserDaoIf对象
        2 动态工厂(忽略)
      -->
      <bean id="factory" class="com.etoak.factory.DaoFactory" 
            factory-method="getDao"></bean>
      <!-- 
        3 FactoryBean接口
            (UserDaoIf)getBean("fb")
            ioc容器会将所有实现了FactoryBean接口的类作为工厂bean对象
        调用工厂bean时返回的对象实例 是 该工厂自动调用其getObject()返回的对象实例
       -->
      <bean id="fb" class="com.etoak.factory.DaoFactoryBean"></bean>
</beans>

UserDaoIf. Java

package com.etoak.dao;
/**
 * 以接口的方式为LoginAction提供登录检查服务
 * 只需要知道LoginAction要实现登录操作需要一个login()方法
 * 不需要知道login()方法如何实现
 * 用到的时候只需要远程调用其他服务器上的实现方法
 * @author D_xiao
 *
 */
public interface UserDaoIf  {
    public boolean login();
}

DaoFactory.java

package com.etoak.factory;

import com.etoak.dao.UserDaoIf;
/**
 * 静态工厂
 * @author D_xiao
 *
 */
public class DaoFactory {
    //UserDaoIf
    private static UserDaoIf dao;
    static{
        dao = new UserDaoIf(){
            public boolean login(){
                //不能实例化具体对象,但能调用远程的东西
                System.out.println("使用webservice技术远程调用其他服务器中的具体实现");
                return true;
            }
        };
    }
    public static UserDaoIf getDao(){
        return dao;
    }
}
DaoFactoryBean.java

package com.etoak.factory;

import org.springframework.beans.factory.FactoryBean;
import com.etoak.dao.UserDaoIf;
/**
 * FactoryBean接口,第三方工厂
 * @author D_xiao
 *
 */
public class DaoFactoryBean implements FactoryBean{

    @Override
    public Object getObject() throws Exception {
        // 当前工厂需要创建的对象实例
        return new UserDaoIf(){
            public boolean login(){
                System.out.println("使用webservice调用其他服务器方法");
                return true;
            }
        };
    }

    @Override
    public Class getObjectType() {
        // 描述当前工厂创建的实例类型
        return UserDaoIf.class;
    }

    @Override
    public boolean isSingleton() {
        // 描述创建的单例状态  单例/ 非单例
        return false;
    }

}
LoginAction.java

package com.etoak.action;

import com.etoak.dao.UserDaoIf;


public class LoginAction {

    private UserDaoIf dao;

    public void setDao(UserDaoIf dao) {
        this.dao = dao;
    }

    public String execute() throws Exception{
        dao.login();
        return "success";
    }
}

Test.java (测试)

package com.etoak.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.etoak.action.LoginAction;

public class Test {
    public static void main(String[] args) throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
          ac = new FileSystemXmlApplicationContext("src/applicationContext.xml");
         LoginAction la = (LoginAction)ac.getBean("action");
         //UserDaoImpl ud = ac.getBean(UserDaoImpl.class);
         la.execute();
    }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值