Java IoC

1、什么是IoC
IoC是一种设计模式,一种设计思想,它的实现一般依赖于JAVA 反射和动态代理技术。
具体解释为控制反转,它意味着将你设计好的类交给系统去控制,而不是在你的类内部控制,这称为控制反转。

2、IoC的好处
比如类A依赖于接口类型为B的某个具体类,一般我们需要在类A中去new一个具体的类对象。但是利用IoC的思想,我们不需要在类A中去直接new一个具体的类对象了,
可以把这个对B接口具体类的依赖的控制权从类A交给平台或者框架去处理,这就是对依赖的控制反转,Spring就使用了这种设计思想。
当我们需要修改这个依赖的具体对象时,我们不需要改具体的业务类的具体代码,而只需更新配置文件即可。
总之,IoC它是面向对象系统设计复杂性和提高面向对象系统可测试性的一个有效的解决方案。

3、IoC的实现技术
IoC的实现技术核心是反射技术,当然它还包括了一些常用的设计模式,如代理模式等,以及XML技术等。

4、一个简单的IoC实现过程

1)创建一个beans.properties文件,用于存放bean的具体实现:

articleDao=bruce.zhao.cms.backend.dao.impl.ArticleDaoImpl  
channelDao=bruce.zhao.cms.backend.dao.impl.ChannelDaoImpl
2)创建一个制造bean的工厂,通过反射来创造写在配置文件里面的那些bean
public class PropertiesBeanFactory implements BeanFactory{  
  
    //该工厂类产生的bean都放在这个map里面  
    Map beans=new HashMap();  
    //默认的properties文件的名字为:beans.properties  
    private String congfigLocation="beans.properties";  
      
    public PropertiesBeanFactory(){  
        init();  
    }  
      
    public PropertiesBeanFactory(String configLocation){  
        setCongfigLocation(configLocation);  
        init();  
    }  
      
    private void init(){  
        try {  
            Properties properties=new Properties();  
              
            //将properties文件load进来  
            properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(congfigLocation));  
            //将properties对象转换为一个set,便于遍历  
            Set set=properties.entrySet();  
            //循环遍历properties文件里面的一条条记录  
            for (Iterator iterator=set.iterator(); iterator.hasNext(); ) {  
                Map.Entry entry=(Map.Entry)iterator.next();  
                String keyString=(String)entry.getKey();  
                String className=(String)entry.getValue();  
                Class clz=Class.forName(className);  
                Object bean= clz.newInstance();  
                //将实例化好的类放进map  
                beans.put(keyString, bean);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        } catch (InstantiationException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        }  
    }  
      
    public Object getBean(String name){  
        return beans.get(name);  
    }  
  
    /** 
     * @return the congfigLocation 
     */  
    public String getCongfigLocation() {  
        return congfigLocation;  
    }  
  
    /** 
     * @param congfigLocation the congfigLocation to set 
     */  
    public void setCongfigLocation(String congfigLocation) {  
        this.congfigLocation = congfigLocation;  
    }  
}
3)创建一个InitBeanFactoryServlet,该servlet在web.xml里面不需要配置对应的map,因为只有在初始化的时候会用到,但是需要设置启动项为0,让他最先初始化。
    <servlet>  
        <description></description>  
        <display-name>InitBeanFactoryServlet</display-name>  
        <servlet-name>InitBeanFactoryServlet</servlet-name>  
        <servlet-class>bruce.zhao.cms.backend.view.InitBeanFactoryServlet</servlet-class>  
        <init-param>  
          <param-name>configLocation</param-name>  
          <param-value>beans.properties</param-value>  
        </init-param>  
        <load-on-startup>0</load-on-startup>  
      </servlet>  
该类的作用:在容器启动的时候调用PropertiesBeanFactory来产生写在properties配置文件里面的类,把他们放在ServletContext里面。
public class InitBeanFactoryServlet extends HttpServlet {  
    private static final long serialVersionUID = 1L;  
      
    public static final String INIT_FACTORY_NAME="_my_bean_factory";  
  
    /* (non-Javadoc) 
     * @see javax.servlet.GenericServlet#init() 
     */  
    @Override  
    public void init(ServletConfig config) throws ServletException {  
        BeanFactory beanFactory=null;  
        String configLocation =config.getInitParameter("configLocation");  
        if (configLocation==null) {  
            //如果在web.xml里面没有配置properties文件的名字则  
            beanFactory=new PropertiesBeanFactory();  
        }else {  
            beanFactory=new PropertiesBeanFactory(configLocation);  
        }  
        config.getServletContext().setAttribute(INIT_FACTORY_NAME, beanFactory);  
    }  
  
} 
4)创建一个BaseServelt,所有别的servlet都继承自他,他的子类会先调用他的service方法,通过反射查看子类里面有没有bean的set方法,如果有就在ServletContext里面获取对应的bean。(第三部的时候,InitBeanFactoryServlet 已经将所有的bean都放到了ServletContext里面)
public class BaseServelt extends HttpServlet {  
    private static final long serialVersionUID = 1L;  
  
    /** 
     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response) 
     */  
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
          
        BeanFactory beanFactory=(BeanFactory) getServletContext().getAttribute(InitBeanFactoryServlet.INIT_FACTORY_NAME);  
          
        Method[] methods=this.getClass().getMethods();  
        for (Method method : methods) {  
            if (method.getName().startsWith("set")) {  
                String propertyName=method.getName().substring(3);  
                StringBuffer sb =new StringBuffer(propertyName);  
                sb.replace(0, 1, (propertyName.charAt(0)+"").toLowerCase());  
                propertyName=sb.toString();  
                Object bean= beanFactory.getBean(propertyName);  
                try {  
                    method.invoke(this, bean);  
                } catch (IllegalArgumentException e) {  
                    e.printStackTrace();  
                } catch (IllegalAccessException e) {  
                    e.printStackTrace();  
                } catch (InvocationTargetException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
          
        super.service(request, response);  
    }  
  
} 

参考:http://whoosh.iteye.com/blog/1133194

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值