程序解耦合思想,关于spring IOC,DI

程序解耦合思想

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调 用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关
系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立 性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。 在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计
应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个 准则就是高内聚低耦合。

程序的耦合

耦合:程序间的依赖关系

包括:类之间的依赖,方法间的依赖

解耦:降低程序间的依赖关系

实际开发中:应该做到:编译期不依赖,运行时才依赖。

解耦的思路:

第一步:使用反射来创建对象,而避免使用new关键字。

第二步:通过读取配置文件来获取要创建的对象全限定类名

例如:使用DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 语句,如果没有对应的依赖,在编译期就会报异常,所有使用Class.forName("com.mysql.jdbc.Driver"); 用反射的方式读取配置文件,降低耦合度

public class JdbcDemo1 {
    public static void main(String[] args) throws  Exception{
        //1.注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/eesy","root","1234");
        //3.获取操作数据库的预处理对象
        PreparedStatement pstm = conn.prepareStatement("select * from account");
        //4.执行SQL,得到结果集
        ResultSet rs = pstm.executeQuery();
        //5.遍历结果集
        while(rs.next()){
            System.out.println(rs.getString("name"));
        }
        //6.释放资源
        rs.close();
        pstm.close();
        conn.close();
    }
}

以下代码,private IAccountDao accountDao = new AccountDaoImpl(); 如果dao层没有对应的实现类,那么就会发生编译时异常,程序耦合度高,不够健壮

public class AccountServiceImpl implements IAccountService {

    private IAccountDao accountDao = new AccountDaoImpl();

    //private IAccountDao accountDao = (IAccountDao)BeanFactory.getBean("accountDao");

//    private int i = 1;

    public void  saveAccount(){
        int i = 1;
        accountDao.saveAccount();
        System.out.println(i);
        i++;
    }
}

首先配置一个properties文件

accountService=com.itheima.service.impl.AccountServiceImpl
accountDao=com.itheima.dao.impl.AccountDaoImpl
/**
 * 一个创建Bean对象的工厂
 *
 * Bean:在计算机英语中,有可重用组件的含义。
 * JavaBean:用java语言编写的可重用组件。
 *      javabean >  实体类
 *
 *   它就是创建我们的service和dao对象的。
 *
 *   第一个:需要一个配置文件来配置我们的service和dao
 *           配置的内容:唯一标识=全限定类名(key=value)
 *   第二个:通过读取配置文件中配置的内容,反射创建对象
 *
 *   我的配置文件可以是xml也可以是properties
 */
public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;

     //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            }
        }catch(Exception e){
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }


 public static Object getBean(String beanName){
        Object bean = null;
        try {
            String beanPath = props.getProperty(beanName);
            System.out.println(beanPath);
            bean = Class.forName(beanPath).newInstance();//每次都会调用默认构造函数创建对象
        }catch (Exception e){
            e.printStackTrace();
        }
        return bean;
    }
   
}

单例模式

public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;

    //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
    private static Map beans;

    //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //实例化容器
            beans = new HashMap();
            //取出配置文件中所有的Key
            Enumeration keys = props.keys();
            //遍历枚举
            while (keys.hasMoreElements()){
                //取出每个Key
                String key = keys.nextElement().toString();
                //根据key获取value
                String beanPath = props.getProperty(key);
                //反射创建对象
                Object value = Class.forName(beanPath).newInstance();
                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }

    /**
     * 根据bean的名称获取对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }

}

[图片上传失败...(image-ec806-1596714253764)]

[图片上传失败...(image-b3347b-1596714253764)]

IOC

实例化 Bean 的三种方式

第一种方式:使用默认无参构造函数

第二种方式:spring管理静态工厂-使用静态工厂的方法创建对象 /**

模拟一个静态工厂,创建业务层实现类 */ public class StaticFactory { public static IAccountService createAccountService(){ return new AccountServiceImpl(); } }

第三种方式:spring管理实例工厂-使用实例工厂的方法创建对象 /**

模拟一个实例工厂,创建业务层实现类 * 此工厂创建对象,必须现有工厂实例对象,再调用方法 */ public class InstanceFactory { public IAccountService createAccountService(){ return new AccountServiceImpl(); } }

  
  


 
 
 

  

 

 

DI

依赖注入的概念

依赖注入:Dependency Injection。它是 spring 框架核心 ioc 的具体实现。 我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。 ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。 那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。 简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

构造函数注入
顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置
的方式,让 spring 框架来为我们注入。

public class AccountServiceImpl implements IAccountService {    
    private String name; 
    private Integer age;  
    private Date birthday;
    
    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;  
        this.age = age;   
        this.birthday = birthday;  
    } 
 
    @Override  
    public void saveAccount() {  
        System.out.println(name+","+age+","+birthday);   
    }
} 
 
    
  
 

set 方法注入

顾名思义,就是在类中提供需要注入成员的 set 方法

public class AccountServiceImpl implements IAccountService {    
    private String name;  
    private Integer age;  
    private Date birthday;    
    public void setName(String name) {   
        this.name = name;  
    }  
    public void setAge(Integer age) {   
        this.age = age;  
    }  
    public void setBirthday(Date birthday) {
        this.birthday = birthday;  
    } 
 
    @Override  
    public void saveAccount() {
        System.out.println(name+","+age+","+birthday);   
    } 
} 
   
     
       
     

注入集合属性

顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。

public class AccountServiceImpl implements IAccountService {
    private String[] myStrs;  
    private List myList;  
    private Set mySet;  
    private Map myMap;  
    private Properties myProps;    
    public void setMyStrs(String[] myStrs) { 
        this.myStrs = myStrs;  
    }  
    public void setMyList(List myList) { 
        this.myList = myList;  
    }  
    public void setMySet(Set mySet) {   
        this.mySet = mySet; 
    }  
    public void setMyMap(Map myMap) { 
        this.myMap = myMap; 
    }  
    public void setMyProps(Properties myProps) { 
        this.myProps = myProps;  
    } 
 
     @Override 
    public void saveAccount() {
        System.out.println(Arrays.toString(myStrs));  
        System.out.println(myList);  
        System.out.println(mySet);  
        System.out.println(myMap);   
        System.out.println(myProps); 
    }
} 

      
      
     
        
            AAA
            BBB
            CCC
         
     
      
       
            
            AAA    
            BBB    
            CCC   
          
     
       
    
            
            AAA    
            BBB    
            CCC   
          
     
      
       
         
            aaa    
            bbb   
         
     
    
      
            
             
                
                bbb 
               
           
     

你可能感兴趣的:(程序解耦合思想,关于spring IOC,DI)