欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

spring最核心思想--ioc控制反转,

来源: javaer 分享于  点击 9362 次 点评:95

spring最核心思想--ioc控制反转,


一核心概念    

控制反转:将bean的生成交给容器,程序可以从容器中获取指定的bean。

个人理解:此优势也是spring能够流行并成为java主流框架的主要原因,java是帮助java程序员以对象的方式管理 内存,而spring则是一个管理对象的框架。如果使用spring,在开发中基本上不需要考虑内存相关的问题。

接下来从一个设计者的思路去交流下spring的设计思路

 

二需求

基于以上的需求,我们需要做的核心的需求的是:生成,管理bean,向使用者提供。

三设计

看到这,是不是第一反应就是可以用工厂模式,没错,spring框架中针对此设计也是工厂模式。核心类为Beanactory,核心方法为getBean()。

1 public interface BeanFactory {
2     /**
3      * 获取bean
4      * @param name bean的名字
5      * @return bean 实例
6      * @throws Exception
7      */
8     Object getBean(String name) throws Exception;
9 }

现在有个工厂,同时我们面对2个问题:

1BeanFactory如何知道生成什么样的bean(bean是由用户指定的)?

2用户如何定义一个bean,便于用户使用也便于beanFactory?

 

接下来先考虑第二个问题,现在谁也不知道用户将定义怎样的bean,那就来个万能大法,先定义的一个接口专门做这个事,接口为BeanDefinition。

回到第一个问题,我们如何将BeanDefinition告诉给BeanFactory?解决这个问题同时我们还要考虑可扩展性。这个解决方案是注册模式。

public interface BeanDefinitionRegistry {
  /**
   * 注册bean定义
  * @param beanName bean名称(bean的唯一标识)
  * @param beanDefinition bean定义
  * @throws BeanDefinitionRegistException 注册异常
  */
  void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionRegistException;
}

 

每个bean通过BeanDefinitionRegistry接口通知给BeanFactory。

目前只剩下一个问题:BeanDefinition如何定义,通俗点就是BeanDefinition里面都有什么。

Bean生成都有哪些情况,

1是否单例

2bean类名

3生成方式:

  3.1指定初始化方法

    必须的信息:bean的类名

  3.2通过工厂模式

    3.2.1静态的

    

public class PersonFactory{  

  public static Person getPerson(){
   return new Person();
  }
}

 

    3.2.2成员方法

public class PersonFactory{  
    public Person getPerson(){
       return new Person();  
    } 
} 

   工厂模式下,必须获取的信息如下:工厂bean的命,工厂方法名

  3.3new的方式

4销毁的方法

具体接口如下:

public interface BeanDefinition {

    String SCOPE_SINGLETION = "singleton";

    String SCOPE_PROTOTYPE = "prototype";

    /**
     * 类
     */
    Class<?> getBeanClass();

    /**
     * Scope
     */
    String getScope();

    /**
     * 是否单例
     */
    boolean isSingleton();

    /**
     * 是否原型
     */
    boolean isPrototype();

    /**
     * 工厂bean名
     */
    String getFactoryBeanName();

    /**
     * 工厂方法名
     */
    String getFactoryMethodName();

    /**
     * 初始化方法
     */
    String getInitMethodName();

    /**
     * 销毁方法
     */
    String getDestroyMethodName();

    /**
     * 校验bean定义的合法性
     */
    default boolean validate() {
        // 没定义class,工厂bean或工厂方法没指定,则不合法。
        if (this.getBeanClass() == null) {
            if (StringUtils.isBlank(getFactoryBeanName()) || StringUtils.isBlank(getFactoryMethodName())) {
                return false;
            }
        }

        // 定义了类,又定义工厂bean,不合法
        if (this.getBeanClass() != null && StringUtils.isNotBlank(getFactoryBeanName())) {
            return false;
        }

        return true;
    }

}

 

 

ioc容器的主要设计均已设计完成。

简单的实现源代码如下:

package core.ioc.impl; import core.exception.BeanDefinitionRegistException; import core.ioc.BeanDefinition; import core.ioc.BeanDefinitionRegistry; import core.ioc.BeanFactory; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.xml.ws.WebServiceException; import java.io.Closeable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; public class DefaultBeanFactory implements BeanFactory, BeanDefinitionRegistry, Closeable { private final Log logger = LogFactory.getLog(DefaultBeanFactory.class); //存在beanDefinition的缓存 private Map<String,BeanDefinition> beanDefinitionMap= new ConcurrentHashMap<>(256); //存放单例bean实例的缓存 private Map<String,Object> beanMap = new ConcurrentHashMap<>(256); //获取bean实例 public Object getBean(String name) throws Exception { return this.doGetBean(name); } protected Object doGetBean(String beanName) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //验证bean不能为空 Objects.requireNonNull(beanName,"beanName不能为空"); //查看是否已经创建,如果已经创建则直接从缓存中取得返回 Object instance = beanMap.get(beanName); if(null!=instance){ return instance; } //如果没有创建,则需要创建, BeanDefinition bd = this.getBeanDefinition(beanName); Objects.requireNonNull(bd,"beanDefinition 不能为空"); Class<?> type=bd.getBeanClass(); if(type!=null){ if(StringUtils.isBlank(bd.getFactoryMethodName())){ //构造方法来构造对象 instance =this.createInstanceByConstructor(bd); }else{ //通过静态工厂方法创建对象 instance=this.createInstanceByStaticFactoryMethod(bd); } }else{ //通过工厂bean方式来构造对象 instance=this.createInstanceByFactoryBean(bd); } //执行初始化方法,比如说给属性赋值等 this.doInit(bd,instance); //如果是单例,则将bean实例放入缓存中 if(bd.isSingleton()){ beanMap.put(beanName,instance); } return instance; } /** * 通过构造方法来构造对象 * @param bd dean定义 * @return bean实例 * @throws IllegalAccessException * @throws InstantiationException */ private Object createInstanceByConstructor(BeanDefinition bd) throws IllegalAccessException, InstantiationException { return bd.getBeanClass().newInstance(); } /** * 通过静态工厂方法创建bean * @param bd bean定义 * @return bean 实例 * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalAccessException */ private Object createInstanceByStaticFactoryMethod(BeanDefinition bd) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class<?> type=bd.getBeanClass(); Method m=type.getMethod(bd.getFactoryMethodName(),null); return m.invoke(type,null); } /** * 通过工厂bean 方式来构造对象 * @param bd * @return * @throws InvocationTargetException * @throws IllegalAccessException * @throws NoSuchMethodException */ private Object createInstanceByFactoryBean(BeanDefinition bd) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { Object factoryBean =this.doGetBean(bd.getFactoryBeanName()); Method m=factoryBean.getClass().getMethod(bd.getFactoryMethodName(),null); return m.invoke(factoryBean,null); } /** * 初始化 * @param bd * @param instance * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalAccessException */ private void doInit(BeanDefinition bd,Object instance) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { if(StringUtils.isNotBlank(bd.getInitMehtodName())){ Method m=instance.getClass().getMethod(bd.getInitMehtodName(),null); m.invoke(instance,null); } } @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionRegistException { Objects.requireNonNull(beanName,"注册bean需要给入beanName"); Objects.requireNonNull(beanDefinition,"注册bean需要给入beanDefinition"); //检验给如的bean是否合法 if(!beanDefinition.validata()){ throw new BeanDefinitionRegistException(String.format("名字为[%s]的bean的定义不合法:%s",beanName,beanDefinition)); } //验证beanDefinition已经存在 if(this.containBeanDefinition(beanName)){ throw new BeanDefinitionRegistException(String.format("名字为[%s]的bean定义已经存在:%s", beanName,this.getBeanDefinition(beanName))); } this.beanDefinitionMap.put(beanName,beanDefinition); } /** * 获取beanDefinition * @param beanName bean的名称 唯一标识 * @return beanDefinition */ @Override public BeanDefinition getBeanDefinition(String beanName) { return this.beanDefinitionMap.get(beanName); } /** * 验证beanDefinition是否已经存在 * @param beanName bean的名称 唯一标识 * @return true:已存在 false:不存在 */ @Override public boolean containBeanDefinition(String beanName) { return this.beanDefinitionMap.containsKey(beanName); } /** * 执行指定的销毁方法 * @throws WebServiceException */ @Override public void close() throws WebServiceException { //执行单例实例的销毁方法 for(Map.Entry<String,BeanDefinition> e:this.beanDefinitionMap.entrySet()){ String beanName=e.getKey(); BeanDefinition bd=e.getValue(); if(bd.isSingleton() && StringUtils.isNotBlank(bd.getDestroyMethodName())){ Object instance = this.beanMap.get(beanName); try { Method m = instance.getClass().getMethod(bd.getDestroyMethodName()); m.invoke(instance,null); } catch (NoSuchMethodException e1) { logger.error(String.format("执行bean[%s] %s 的 销毁方法异常!",beanName,bd), e1); e1.printStackTrace(); } catch (IllegalAccessException e1) { logger.error(String.format("执行bean[%s] %s 的 销毁方法异常!",beanName,bd), e1); e1.printStackTrace(); } catch (InvocationTargetException e1) { logger.error(String.format("执行bean[%s] %s 的 销毁方法异常!",beanName,bd), e1); e1.printStackTrace(); } } } } } DefaultBeanFactory
package core.ioc.impl;

import core.ioc.BeanDefinition;
import org.apache.commons.lang3.StringUtils;

public class GenericBeanDefinition implements BeanDefinition {


    private Class<?> beanClass;

    //是否为单例
    private String scope = BeanDefinition.SCOPE_SINGLETION;

    //bean工厂的名称
    private String factoryBeanName;
    //bean工厂方法名
    private String factoryMethodName;

    //初始化方法
    private String initMethodName;
    //销毁方法
    private String destroyMethodName;




    /**
     * 自动生成设置的方法 start
     */
    public void setBeanClass(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public void setScope(String scope) {
        if(StringUtils.isNoneBlank(scope)){
            this.scope = scope;
        }
    }

    public void setFactoryBeanName(String factoryBeanName) {
        this.factoryBeanName = factoryBeanName;
    }

    public void setFactoryMethodName(String factoryMethodName) {
        this.factoryMethodName = factoryMethodName;
    }

    public void setInitMethodName(String initMethodName) {
        this.initMethodName = initMethodName;
    }

    public void setDestroyMethodName(String destroyMethodName) {
        this.destroyMethodName = destroyMethodName;
    }
    /**
     * 自动生成设置的方法 end
     */


    @Override
    public Class<?> getBeanClass() {
        return this.beanClass;
    }

    @Override
    public String getScope() {

        return this.scope;
    }

    @Override
    public boolean isSingleton() {
        return BeanDefinition.SCOPE_SINGLETION.equals(this.scope);
    }

    @Override
    public boolean isPrototype() {
        return BeanDefinition.SCOPE_PROTOTYPE.equals(this.scope);
    }

    @Override
    public String getFactoryBeanName() {
        return this.factoryBeanName;
    }

    @Override
    public String getFactoryMethodName() {
        return this.factoryMethodName;
    }

    @Override
    public String getInitMehtodName() {
        return this.initMethodName;
    }

    @Override
    public String getDestroyMethodName() {
        return this.destroyMethodName;
    }



    @Override
    public String toString() {
        return String.format("GenericBeanDefinition [beanClass=%s, scope=%s, factoryBeanName=%s, " +
                "factoryMethodName=%s, initMethodName=%s, destroyMethodName=%s]",
                beanClass,scope,factoryBeanName,factoryMethodName,initMethodName,destroyMethodName);
    }

    /**
     * 疑问: 为什么要重写equals 方法
     *
     * 重写equals方法需要注意以下几点:
     * 1自反性:对于任何非空引用x,x.equals(x)应该返回true
     * 2对称:对于任何引用x,y,如果x.equals(y) 返回true,那么 y.equals(x)也应该返回true。
     * 3传递性:对于任何引用x,y和z,如果x=y 为true,那么y=z也一定为true,x=z也一定为true。
     * 4一致性:如果x和y引用的对象没有发生变化,那么返回调用x.equals(y),应该返回同样的结果。
     * 5非空性:对于任意非空引用x,x.equals(null)应该返回false。
     *
     * 重写equals方法,就必须重写hashCode
     * 原因是HashMap的需要
     */

    @Override
    public boolean equals(Object obj) {
        if(this==obj){
            return true;
        }

        if(null==obj){
            return false;
        }

        if(getClass() !=obj.getClass()){
            return false;
        }

        GenericBeanDefinition other=(GenericBeanDefinition) obj;

        //验证每个属性是否相当,只有当每个属性均相等时,才是一个对象
        if(beanClass ==null){
            if(other.beanClass!=null){
                return false;
            }
        }else if(!beanClass.equals(other.beanClass)){
            return false;
        }

        if(destroyMethodName== null){
            if(other.destroyMethodName!=null){
                return false;
            }
        }else if(!destroyMethodName.equals(other.destroyMethodName) ){
            return false;
        }

        if(factoryBeanName== null){
            if(other.factoryBeanName!=null){
                return false;
            }
        }else if(!factoryBeanName.equals(other.factoryBeanName) ){
            return false;
        }

        if(factoryMethodName== null){
            if(other.factoryMethodName!=null){
                return false;
            }
        }else if(!factoryMethodName.equals(other.factoryMethodName) ){
            return false;
        }

        if(initMethodName== null){
            if(other.initMethodName!=null){
                return false;
            }
        }else if(!initMethodName.equals(other.initMethodName) ){
            return false;
        }

        if(scope== null){
            if(other.scope!=null){
                return false;
            }
        }else if(!scope.equals(other.scope) ){
            return false;
        }


        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((beanClass == null) ? 0 : beanClass.hashCode());
        result = prime * result + ((destroyMethodName == null) ? 0 : destroyMethodName.hashCode());
        result = prime * result + ((factoryBeanName == null) ? 0 : factoryBeanName.hashCode());
        result = prime * result + ((factoryMethodName == null) ? 0 : factoryMethodName.hashCode());
        result = prime * result + ((initMethodName == null) ? 0 : initMethodName.hashCode());
        result = prime * result + ((scope == null) ? 0 : scope.hashCode());
        return result;
    }
}

 

相关文章

    暂无相关文章
相关栏目:

用户点评