import java.sql.*; /** * 程序的耦合 */ public class Demo1 { public static void main(String[] args) throws SQLException { //1.注册驱动 DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); //2.获取连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","123456"); //3.获取操作数据库的预处理对象 PreparedStatement preparedStatement = conn.prepareStatement("select * from sp_attribute"); //4.获取结果集 ResultSet resultSet = preparedStatement.executeQuery(); //5.遍历结果集 while (resultSet.next()){ System.out.println(resultSet.getString("attr_name")); } //6.释放资源 resultSet.close(); preparedStatement.close(); conn.close(); } }
一段Demo给出来,表明了该程序耦合性较高。如果要做迁移之类的动作,改动可能较大。
后来将DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());改为了Class.forName()的方式。这一小段的修改,使得程序从编译时报错变为了运行时报错。
第二段Demo:
/** * 业务层接口 */ public interface AccountService { void saveAccount(); }
import com.springpractise.demo.Dao.AccountDao; import com.springpractise.demo.Dao.AccountDaoImpl; import com.springpractise.demo.factory.BeanFactory; /** * 业务层实现类 */ public class AccountServiceImpl implements AccountService { private AccountDao accountDao = new AccountDaoImpl(); //private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDaoImpl"); @Override public void saveAccount() { accountDao.saveAccount(); } }
public interface AccountDao { void saveAccount(); }
public class AccountDaoImpl implements AccountDao{ @Override public void saveAccount() { System.out.println("保存了账户"); } }
import com.springpractise.demo.factory.BeanFactory; import com.springpractise.demo.service.AccountService; import com.springpractise.demo.service.AccountServiceImpl; public class Clinet { public static void main(String[] args) { AccountService accountService = new AccountServiceImpl(); //AccountService accountService = (AccountService) BeanFactory.getBean("accountService"); accountService.saveAccount(); } }
这一段代码再次展示了高耦合。
AccountService accountService = new AccountServiceImpl();
private AccountDao accountDao = new AccountDaoImpl();
这两句话表示,在编译的时候,需要AccountServiceImpl和AccountDaoImpl。一旦删除,编译无法成功。
后来做了处理,增加了:
import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 一个创建Bean对象的工厂 * Bean:在计算机英语中有可重用组件的含义 * javaBean:用java语言编写的可重用组件 * 创建javaBean: * 第一个:需要一个配置文件来配置service和dao * 配置的内容:唯一标志 = 全限定类名(key = value) * 第二个:通过读取配置文件中配置的内容,反射创建对象 * * 配置文件可以是xml也可以是properties * */ public class BeanFactory { //定义一个Properties对象 private static Properties properties; //使用静态代码块为Properties对象赋值 static { try { //实例化对象 properties = new Properties(); //获取properties文件的流对象(通过BeanFactory来获取文件) InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); properties.load(in); } catch (IOException e) { throw new ExceptionInInitializerError("初始化properties失败"); } } /** * 根据Bean的名称获取Bean对象 * @param BeanName * @return */ public static Object getBean(String BeanName){ Object bean = null; try { String beanPath = properties.getProperty(BeanName); bean = Class.forName(beanPath).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return bean; } }
读取的Bean.properties文件在resource的根目录下,内容为:
accountService = com.springpractise.demo.service.AccountServiceImpl accountDaoImpl = com.springpractise.demo.Dao.AccountDaoImpl
因此,后期只需将
private AccountDao accountDao = new AccountDaoImpl();
替换为:
private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDaoImpl");
将
AccountService accountService = new AccountServiceImpl();
替换为:
AccountService accountService = (AccountService) BeanFactory.getBean("accountService");
即可。
通过反射机制,根据Bean名称找到对应的类,然后再实例化。可以看到,现在只需读取配置文件就可以了,如果将AccountService和AccountDao文件删除,依然能够编译成功。
参考:https://www.bilibili.com/video/BV1Sb411s7vP?p=13
代码连接是这个吗:https://download.csdn.net/download/qq_35383788/13118014