Spring-IoC入门理解
新建一个Maven工程
在pom文件中导入需要的依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lps</groupId> <artifactId>Spring-002-first</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <!-- 依赖--> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.23</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> </project>
我这里用jdk17
可以ctrl+shift+ait+s调出structure进行jdk的配置 看个人使用情况配置
public class User { //默认情况下spring通过反射机制 调用类的无参构造方法来实例化对象 //实现原理如下 //Class hhh = Class.forName("com.lps.bean.User"); //hhh.newInstance(); public User() { System.out.println("User的无参构造方法执行"); } //当我们定义了有参构造器 无参构造器就无法实例了 所以记得定义下无参 //No default constructor found; // nested exception is java.lang.NoSuchMethodException: com.lps.bean.User.<init>() public User(User u) { System.out.println("User的无参构造方法执行"); } }
public class Vip { public Vip() { System.out.println("vip的无参构造器运行"); } }
public class UserDaoImplForMysql { public UserDaoImplForMysql() { } public void insert(){ System.out.println("刘品水正在使用mysql保存信息"); } }
接下来是spring的xml配置
spring.xml
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <!-- id是bean的身份证号 不能重复 是唯一的标识--> <bean id="userBean" class="com.lps.bean.User"></bean> <!-- <bean id="userBean" class="com.lps.bean.Vip"></bean>--> <!-- spring--> <bean id="UserDaoImplForMysql" class="com.lps.dao.UserDaoImplForMysql"></bean> </beans>
bean.xml
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <!-- id是bean的身份证号 不能重复 是唯一的标识--> <bean id="userBean" class="com.lps.bean.User"></bean> <!-- <bean id="userBean" class="com.lps.bean.Vip"></bean>--> <!-- spring--> <bean id="UserDaoImplForMysql" class="com.lps.dao.UserDaoImplForMysql"></bean> </beans>
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <bean id="vip0" class="com.lps.bean.Vip"></bean> <bean id="userBean" class="com.lps.bean.User"></bean> <bean id="UserDaoImplForMysql0" class="com.lps.dao.UserDaoImplForMysql"></bean> <!-- 配置java.util.Data Bean--> <bean id="nowTime" class="java.util.Date"></bean> </beans>
最后写一个测试类来感受IoC的好处即可
package com.lps.test; import com.lps.bean.User; import com.lps.dao.UserDaoImplForMysql; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import java.text.SimpleDateFormat; import java.util.Date; /** * ClassName: FirstSpringTest * Description: * Date: 2022/11/18 22:07 * <author> <time> <version> <desc> * 刘品水 2022/11/18 22:07 @Version 1.0 描述 */ public class FirstSpringTest { @Test public void testBeginInitBean(){ //执行以下代码就会执行实例化对象了 并不是getBean()方法调用的时候 new ClassPathXmlApplicationContext("spring.xml"); } @Test public void testBeanFactory(){ //ApplicationContext接口的超级父类是BeanFactory(Bean工厂) //BeanFactory是IoC容器的顶级接口 //Spring的IoC容器底层使用了;工厂模式 //Spring底层的IoC是通过:XML解析、工厂模式、反射机制 BeanFactory context = new ClassPathXmlApplicationContext("spring.xml"); User bean = context.getBean("userBean", User.class); System.out.println(bean); } @Test public void testXmlPath(){ FileSystemXmlApplicationContext context //= new FileSystemXmlApplicationContext("G:/JavaProject/Spring/beans.xml"); = new FileSystemXmlApplicationContext("G:\\JavaProject\\Spring\\beans.xml"); //用途不同 //1、“\”:“\”只能用来表示目录。 //2、“/”:“/”技能作为除法符号或者间隔符号使用,也能用来表示目录。 Date nowTime = context.getBean("nowTime", Date.class); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:ss:SSS"); String nowtime = format.format(nowTime); System.out.println(nowtime); } @Test public void testFirstSpringCode(){ //ApplicationContext应用上下文 spring容器 是一个接口 有很多实现类 其中有一个叫ClassPathXmlApplicationContext //ClassPathXmlApplicationContext:专门从类路径加载spring配置文件的spirng上下文对象 /*ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring.xml","bean.xml");*/ ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring.xml","bean.xml","xml/beans.xml"); //这段代码只要执行 相当于启动了spring容器 解析spring.xml文件 实例化所有的spring文件 Object userBean = applicationContext.getBean("userBean"); System.out.println(userBean); Object userDaoImplForMysql = applicationContext.getBean("UserDaoImplForMysql"); System.out.println(userDaoImplForMysql); System.out.println("==========================================="); /* ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean.xml");*/ //根据public ClassPathXmlApplicationContext(String... configLocations) throws BeansException { // this(configLocations, true, (ApplicationContext)null); // } //所以后面可以直接跟着写,"bean.xml" 可以指定多个路径 Object vip = applicationContext.getBean("vip"); Object userDaoImplForMysql1 = applicationContext.getBean("UserDaoImplForMysql"); System.out.println(userDaoImplForMysql1); System.out.println(vip); System.out.println("=========="); Object vip0 = applicationContext.getBean("vip0"); System.out.println(vip0); System.out.println("----------------------------"); // Object nowTime = applicationContext.getBean("nowTime"); // Date nowTime = (Date)applicationContext.getBean("nowTime"); //不想强制转换可以这样做 Date nowTime = applicationContext.getBean("nowTime", Date.class); System.out.println(nowTime); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:ss:SSS"); String format = simpleDateFormat.format(nowTime); System.out.println("北京时间现在是:"+format); System.out.println("====================="); //强转之后可以调用UserDaoImplForMysql的方法 UserDaoImplForMysql userDaoImplForMysql2 = applicationContext.getBean("UserDaoImplForMysql", UserDaoImplForMysql.class); userDaoImplForMysql2.insert(); } }
BeanFactory是IoC容器的顶级接口
***OCP***
Open-Closed Principle软件设计中的“开-闭原则”
这个原则最早是由Bertrand Meyer提出,英文的原文是:Software entities should be open for extension,
but closed for modification.
意思是说,一个软件实体应当对扩展开放,对修改关闭.也就是说,我们在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,
换句话说就是,应当可以在不必修改源代码的情况下改变这个模块的行为.
满足OCP的设计给系统带来两个无可比拟的优越性.
1.通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性.
2.已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使变化中的软件系统有一定的稳定性和延续性.
例如:
编程模式中的工厂模式的“工厂方法”支持OCP原则
对扩展开放 对修改关闭
***DIP***
依赖倒置原则(dependency inversion principle)
面向接口编程 面向抽象编程 不要面向具体编程
降低耦合度 提高扩展力
表现层 业务层 持久层不再从上往下依赖
***IOC***
核心概念
1. IoC(Inversion of Control)控制反转
使用对象时,由主动new产生对象转换成,从外部提供对象
在这个过程中,对象的创建控制权由程序转移到外部,此思想称为控制反转。用来减低计算机代码之间的耦合度。
***Spring框架***
*Spring框架实现了控制反转IoC这种思想。
Spring可以帮你new对象
Spring框架可以帮你维护对象和对象之间的关系。
*Spring是一个实现了IoC思想的容器。
*控制反转的实现方式很多种,其中比较重要的依赖注入(Dependency Injection,简称DI),
*还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,
*由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
**依赖注入DI 常见的两种方式
!!!set注入、构造方法注入!!!
依赖:A对象与B对象之间的关系
注入:是一种手段 通过这种手段可以让A对象与B对象产生关系。
依赖注入:对象A和对象B之间的关系,靠注入的手段来维护,为注入包括:set注入和构造器注入
***本节术语
OCP:开闭原则
IoC:控制反转
DIP:依赖倒置
DI:依赖注入
个人总结使用对象时通常是使用new但是如此耦合性太搞了 使用spring就是将对象的创建控制权全部交给Spring来处理 我们只需要设置spring的东西即可