spring框架(IOC)

it2023-10-06  76

1.spring的介绍

spring的2大核心思想: ioc: 控制反转,就是工厂模式。 将对象的创建和销毁交给了spring aop:面向切面的编程,就是动态代理。 在不修改源码的情况下,对功能进行增强。

2.spring的ioc

2.1 工厂模式

2.1.2 反射解耦

基于多个实现类需要进行功能切换,我们只需要修改配置文件,不需要改java代码,所以不需要重新编译。

UserServlet

package com.itheima.web; import com.itheima.service.UserService; import com.itheima.service.impl.UserServiceImpl; import com.itheima.service.impl.UserServiceImpl2; import java.util.ResourceBundle; public class UserServlet { public static void main(String[] args) { //请求过来,调用servlet的service //UserService userService = new UserServiceImpl2(); //读取配置文件的内容 ResourceBundle rb = ResourceBundle.getBundle("beans"); String classPath = rb.getString("classPath"); UserService userService = null; try { userService = (UserService) Class.forName(classPath).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } userService.login(); } }

UserService

package com.itheima.service; public interface UserService { public void login(); }

UserServiceImpl

package com.itheima.service.impl; import com.itheima.service.UserService; public class UserServiceImpl implements UserService { @Override public void login() { System.out.println("登录功能"); } }

UserServiceImpl2

package com.itheima.service.impl; import com.itheima.service.UserService; public class UserServiceImpl2 implements UserService { @Override public void login() { System.out.println("登录功能扩展"); } }

beans.properties

classPath=com.itheima.service.impl.UserServiceImpl2

2.1.2 多例工厂模式

bean.properties

userService=com.it.service.impl.UserServiceImpl roleService=com.it.service.impl.RoleServiceImpl

BeansFacoty

package com.it.utils; import com.it.service.RoleService; import com.it.service.UserService; import java.util.ResourceBundle; /** * 工厂模式:专门用来创建java对象的工具类。 * * 将java对象的创建由new的方式 替换成了 反射+配置的方式来创建对象。 * * * 工厂模式的好处: * 1.解耦 * 2.可以对java中的对象进行管理。 * * * 注意: * 在没有解耦的情况下,我们以前使用对象,都是自己new * 现在有了工厂模式,我们使用对象,都是工厂去创建,我们从工厂去获取。 * 对象的创建权利由我们自己创建,交给了工厂创建。这就是ioc * */ public class BeansFactory { public static Object getBean(String beanName){ //1.读取配置 ResourceBundle rb = ResourceBundle.getBundle("beans"); String classPath = rb.getString(beanName); //2.反射机制创建对象 Object obj = null; try { obj = Class.forName(classPath).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return obj; } public static void main(String[] args) { UserService userService = (UserService) getBean("userService"); System.out.println(userService); RoleService roleService = (RoleService)getBean("roleService"); System.out.println(roleService); } }

2.1.3 单例工厂

package com.it.utils; import com.it.service.RoleService; import com.it.service.UserService; import java.util.HashMap; import java.util.ResourceBundle; import java.util.Map; /** * 工厂模式:专门用来创建java对象的工具类。 * * 将java对象的创建由new的方式 替换成了 反射+配置的方式来创建对象。 * * * 工厂模式的好处: * 1.解耦 * 2.可以对java中的对象进行管理。 * 单例和多例 * * 单例:一个类创建的对象只有一个。节省资源。 * 多例:一个类创建的对象可以有多个。 * * * 如果存在线程安全问题的情况下,不能采用单例。 * 什么情况下会出现线程安全问题? * 1.多并发 * 2.多个线程抢占一个资源,并且做了修改。 * * * 注意: * 在没有解耦的情况下,我们以前使用对象,都是自己new * 现在有了工厂模式,我们使用对象,都是工厂去创建,我们从工厂去获取。 * 对象的创建权利由我们自己创建,交给了工厂创建。这就是ioc * */ public class BeansFactory { /** * 多例工厂 * * 此时我们的工厂创建的是service对象 * 1.是否是并发的? 是。 * 2.是否涉及多个线程抢占一个资源,并且修改了service。 不涉及service的成员变量的更改 * * 是否存在线程安全问题呢?不存在 * 使用单例,性能更好。 * * * @param beanName * @return */ public static Object getBean(String beanName){ //1.读取配置 ResourceBundle rb = ResourceBundle.getBundle("beans"); String classPath = rb.getString(beanName); //2.反射机制创建对象 Object obj = null; try { obj = Class.forName(classPath).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return obj; } private static Map<String,Object> beansMap = new HashMap<>(); /** * 单例工厂 * 第一次创建对象,后续都是获取第一次创建的对象。 * * 1.声明变量,接受创建的对象。 * 2.优先从map中获取,如果有,直接返回。如果没有,创建 * * * * * * @param beanName 需要创建的对象的名字 * @return 返回创建的对象,如果对象创建失败,返回null */ public static Object getBean2(String beanName){ Object obj = beansMap.get(beanName); if(obj==null){ //第一次创建 //1.读取配置 ResourceBundle rb = ResourceBundle.getBundle("beans"); String classPath = rb.getString(beanName); //2.反射机制创建对象 try { obj = Class.forName(classPath).newInstance(); //保存到map,方便下次直接获取 beansMap.put(beanName,obj); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return obj; } public static void main(String[] args) { UserService userService = (UserService) getBean2("userService"); UserService userService2 = (UserService) getBean2("userService"); System.out.println(userService); System.out.println(userService2); // RoleService roleService = (RoleService)getBean("roleService"); // System.out.println(roleService); } }

2.1.4 单例工厂和多例工厂的区别

多例: 1.什么时候用,什么时候创建。 2.一旦创建成功,工厂想要再次操作这个对象,可不可以? 不可以的。 单例: 1.可以第一次用的时候创建,也可以先全部创建好。 2.一旦创建成功,工厂想要再次操作这个对象,可不可以? 可以,只要从map中获取即可。

2.2 spring的使用

2.2.1 spring的入门

步骤: 1.引入spring-context 依赖,spring的ioc核心依赖。 2.编译spring的配置xml 3.通过spring工厂获取对象

1.pom.xml引入依赖

<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.6.RELEASE</version> </dependency> </dependencies>

2.编写spring的applicationContext.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 definitions here --> <bean id="userService" class="com.it.service.impl.UserServiceImpl"></bean> </beans>

3.通过spring的工厂获取对象

package com.it.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { public static void main(String[] args) { //1.创建spring的工厂 ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //2.通过spring的工厂获取对象 Object userService = ac.getBean("userService"); System.out.println(userService); } }

2.2.2 spring的工厂类(了解)

BeanFactory: spring工厂的顶层接口 applicationContext: BeanFactory的子接口 FileSystemXmlApplicationContext: 基于绝对路径的xml的工厂 ClassPathXmlApplicationContext: 基于相对路径的xml的工厂 2者的区别就是:创建(单例)对象的时间不一样 BeanFactory: 什么时候使用,什么时候创建 applicationContext: 工厂初始化时,全部创建成功

2.2.3 spring的bean标签详解

<?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 definitions here --> <!-- bean标签: 创建对象,将对象装配到spring容器(泛指spring工厂类)。 id: 对象的唯一标识 class:实现类的路径,底层就是通过反射机制创建对象的。 init-method: 对象创建时,要调用的初始化方法 destroy-method: 对象销毁时,要调用的销毁方法 scope: singleton: 单例(默认) prototype: 多例 对象的生命周期: applicationContext: 工厂初始化时,对象就创建完毕。(单例情况下) 单例: 工厂初始化时创建对象。 只要工厂存在,对象就存在。 工厂销毁,对象销毁。 多例: 什么时候用,什么时候创建。 工厂存在,对象存在。 工厂销毁,对象不销毁。对象只能等待垃圾回收机制回收。 --> <bean id="userService" scope="prototype" init-method="init" destroy-method="destroy" class="com.it.service.impl.UserServiceImpl"></bean> </beans>

test:

package com.it.test; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class SpringTest { public static void main(String[] args) { System.out.println("**************工厂初始化start*********************"); //1.创建spring的工厂 //ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); // Resource resource = new ClassPathResource("applicationContext.xml"); // BeanFactory ac = new XmlBeanFactory(resource); System.out.println("**************工厂初始化end*********************"); //2.通过spring的工厂获取对象 Object userService = ac.getBean("userService"); Object userService2 = ac.getBean("userService"); System.out.println(userService); System.out.println(userService2); //销毁工厂 System.out.println("*************销毁工厂*********************8"); ac.close(); } }

2.2.4 spring创建对象的3种方式

1.默认无参构造 2.工厂类的静态方法 3.工厂类的动态方法

applicationContext.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"> <!-- spring创建对象的4种方式 1.默认无参构造 2.工厂类的静态方法 3.工厂类的动态方法 4.BeanFactory接口方式,ssm整合再去介绍 --> <!-- 默认无参构造方式--> <bean id="userService" class="com.it.service.impl.UserServiceImpl"></bean> <!-- 工厂类的静态方式 --> <bean id="userService2" class="com.it.utils.BeanFactory" factory-method="getUserService"></bean> <!-- 工厂类的动态方法--> <bean id="factoryBean2" class="com.it.utils.BeanFactory2"></bean> <bean id="userService3" factory-bean="factoryBean2" factory-method="getUserService" ></bean> </beans>

UserServiceImpl

package com.it.service.impl; import com.it.service.UserService; public class UserServiceImpl implements UserService { public UserServiceImpl() { System.out.println("UserServiceImpl的无参构造被调用了"); } }

BeanFactory工厂类的静态方法

package com.it.utils; import com.it.service.UserService; import com.it.service.impl.UserServiceImpl; public class BeanFactory { public static UserService getUserService(){ System.out.println("工厂类的静态方法"); return new UserServiceImpl(); } }

BeansFactroy2工厂类的动态方法

package com.it.utils; import com.it.service.UserService; import com.it.service.impl.UserServiceImpl; public class BeanFactory2 { public UserService getUserService(){ System.out.println("工厂类的静态方法"); return new UserServiceImpl(); } }

2.2.5 spring的DI

Dependency Injection (依赖注入):spring创建对象的时候,给对象的属性赋值,就是依赖注入。

2.2.5.1 有参构造

UserDao

package com.it.dao; public interface UserDao { public void findUserByUser(); }

UserDaoImpl

package com.it.dao.impl; import com.it.dao.UserDao; public class UserDaoImpl implements UserDao { @Override public void findUserByUser() { System.out.println("查询用户信息"); } }

UserService

package com.it.service; public interface UserService { public void login(); }

UserServiceImpl

package com.it.service.impl; import com.it.dao.UserDao; import com.it.dao.impl.UserDaoImpl; import com.it.service.UserService; public class UserServiceImpl implements UserService { private String username; private Integer age; private String game; private UserDao userDao; public UserServiceImpl(String username, Integer age, String game, UserDao userDao) { this.username = username; this.age = age; this.game = game; this.userDao = userDao; } public UserServiceImpl() { } @Override public void login() { userDao.findUserByUser(); } }

Test

package com.it.test; import com.it.service.UserService; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class SpringTest { //这是一个servlet public static void main(String[] args) { //调用service ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserService userService = (UserService)ac.getBean("userService3"); userService.login(); } }

applicationContext.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="userService" class="com.it.service.impl.UserServiceImpl"> <!-- 给哪个属性赋什么值 确定属性 name: 通过属性名确定属性 type: 通过属性的类型确定属性 index: 通过索引来确定属性 赋值: value:基本类型的赋值 ref: 引用型类型的赋值 --> <constructor-arg name="age" value="23" ></constructor-arg> <constructor-arg name="game" value="LOL"></constructor-arg> <constructor-arg name="username" value="张三"></constructor-arg> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean> <!-- 有参构造方式--> <bean id="userService2" class="com.it.service.impl.UserServiceImpl"> <constructor-arg index="1" value="23" ></constructor-arg> <constructor-arg index="2" value="LOL"></constructor-arg> <constructor-arg index="0" value="张四"></constructor-arg> <constructor-arg index="3" ref="userDao"></constructor-arg> </bean> <!-- 有参构造方式--> <bean id="userService3" class="com.it.service.impl.UserServiceImpl"> <constructor-arg type="java.lang.Integer" value="23" ></constructor-arg> <constructor-arg type="java.lang.String" value="王五"></constructor-arg> <constructor-arg type="java.lang.String" value="LOL"></constructor-arg> <constructor-arg type="com.it.dao.UserDao" ref="userDao"></constructor-arg> </bean> <bean id="userDao" class="com.it.dao.impl.UserDaoImpl"></bean> </beans>

2.2.5.2 set方法

UserServiceImpl

package com.it.service.impl; import com.it.dao.UserDao; import com.it.dao.impl.UserDaoImpl; import com.it.service.UserService; public class UserServiceImpl implements UserService { private String username; private Integer age; private String game; private UserDao userDao; public UserServiceImpl(String username, Integer age, String game, UserDao userDao) { this.username = username; this.age = age; this.game = game; this.userDao = userDao; } public void setUsername(String username) { this.username = username; } public void setAge(Integer age) { this.age = age; } public void setGame(String game) { this.game = game; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } public UserServiceImpl() { } @Override public void login() { userDao.findUserByUser(); } }

applicationContext.xml

<!-- 属性的set方法 --> <bean id="userService4" class="com.it.service.impl.UserServiceImpl"> <!-- name:用来确定属性的。 name属性的值是set的方法名去掉set后的驼峰命名名字。 value:基本类型的属性赋值 ref:引用型类型的属性赋值 --> <property name="username" value="赵六"></property> <property name="age" value="25"></property> <property name="game" value="王者荣耀"></property> <property name="userDao" ref="userDao"></property> </bean>

2.2.5.3 依赖注入的简写方式(了解)

c名称空间(原理采用的是有参构造)

xmlns:c="http://www.springframework.org/schema/c"

p名称空间 (原理采用的是set方法)

xmlns:p="http://www.springframework.org/schema/p" <!-- c名称空间--> <bean id="userService5" class="com.it.service.impl.UserServiceImpl" c:age="18" c:game="王者荣耀" c:username="c罗" c:userDao-ref="userDao"></bean> <!-- p名称空间--> <bean id="userService6" class="com.it.service.impl.UserServiceImpl" p:age="18" p:username="柳岩" p:game="足球" p:userDao-ref="userDao"></bean>

2.2.5.4 复杂类型的注入

UserServiceImpl2

package com.it.service.impl; import com.it.dao.UserDao; import com.it.service.UserService; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.Map; public class UserServiceImpl2 implements UserService { private String[] gameNames; private List<String> dogType; private Set<String> catType; private Map<String,String> map; public void setGameNames(String[] gameNames) { this.gameNames = gameNames; } public void setDogType(List<String> dogType) { this.dogType = dogType; } public void setCatType(Set<String> catType) { this.catType = catType; } public void setMap(Map<String, String> map) { this.map = map; } @Override public void login(){ } }

applicationContext.xml

<!--复杂类型的注入--> <bean id="userService7" class="com.it.service.impl.UserServiceImpl2"> <property name="gameNames"> <array> <value>LOL</value> <value>打豆豆</value> <value>王者荣耀</value> </array> </property> <property name="dogType"> <list> <value>泰日天</value> <value>二哈</value> <value>中华田园犬</value> </list> </property> <property name="catType"> <set> <value>蓝猫</value> <value>橘猫</value> <value>加菲猫</value> </set> </property> <property name="map"> <map> <entry value="bb" key="aa"></entry> </map> </property> </bean>

3.总结

理解了解 1.工厂模式,理解,关键单例工厂和多例工厂的区别,就是在于单例工厂有一个map集合保存bean对象, 多例没有,创建之后直接返回。 2.spring的工厂类 单例模式下,创建对象的时间节点不一样。 BeanFactory: 顶层接口,什么时候用,什么时候创建对象。 ApplicationContext:BeanFactory的子接口。工厂初始化时创建 掌握的 1.spring的2大核心思想 ioc: 控制反转,对象的创建由我们自己new,换成spring工厂创建 aop: 面向切面的编程,底层就是动态代理,在不修改源码的情况下增强功能 2.spring的入门步骤 a.引入spring-context依赖 b.编写spring的配置applicationContext.xml c.通过spring工厂获取对象 ApplicationContext(ClasspathXmlApplicationContext) 3.spring的bean标签 id:唯一标识 class:实现类的路径 init-method:初始化要调用的方法 destroy-method:销毁时要调用的方法 scope: singleton:单例 prototype:多例 4.spring创建对象的3种方式 1.默认无参构造 2.工厂类的静态方法 3.工厂类的动态方法 5.spring的依赖注入 spring在创建对象的时候,给对象的属性赋值,叫做依赖注入。 1.有参构造 <constructor-arg> 确定属性的 name:属性名确定属性 index:索引确定属性 type:类型确定属性 确定值的 value:基本类型赋值 ref:引用类型的赋值 2.set方式 <property> name:用来确定属性的。 name属性的值是set的方法名去掉set后的驼峰命名名字。 value:基本类型的属性赋值 ref:引用型类型的属性赋值

例工厂的区别,就是在于单例工厂有一个map集合保存bean对象, 多例没有,创建之后直接返回。 2.spring的工厂类 单例模式下,创建对象的时间节点不一样。 BeanFactory: 顶层接口,什么时候用,什么时候创建对象。 ApplicationContext:BeanFactory的子接口。工厂初始化时创建

掌握的 1.spring的2大核心思想 ioc: 控制反转,对象的创建由我们自己new,换成spring工厂创建 aop: 面向切面的编程,底层就是动态代理,在不修改源码的情况下增强功能 2.spring的入门步骤 a.引入spring-context依赖 b.编写spring的配置applicationContext.xml c.通过spring工厂获取对象 ApplicationContext(ClasspathXmlApplicationContext) 3.spring的bean标签 id:唯一标识 class:实现类的路径 init-method:初始化要调用的方法 destroy-method:销毁时要调用的方法 scope: singleton:单例 prototype:多例 4.spring创建对象的3种方式 1.默认无参构造 2.工厂类的静态方法 3.工厂类的动态方法 5.spring的依赖注入 spring在创建对象的时候,给对象的属性赋值,叫做依赖注入。 1.有参构造 确定属性的 name:属性名确定属性 index:索引确定属性 type:类型确定属性 确定值的 value:基本类型赋值 ref:引用类型的赋值 2.set方式 name:用来确定属性的。 name属性的值是set的方法名去掉set后的驼峰命名名字。 value:基本类型的属性赋值 ref:引用型类型的属性赋值

最新回复(0)