1. Spring IOC
-
Spring框架
1.概念 Spring是众多开源java项目中的一员,基于分层的javaEE应用一站式轻量级开源框架,主要核心是IOC(控制反转/依赖注入)与 AOP(面向切面)两大技术,实现项目在开发过程中的轻松解耦,提高项目的开发效率。 在项目中引入Spring立即可以带来下面的好处: 降低组件之间的耦合度,实现软件各层之间的解耦。 可以使用容器提供的众多服务。 容器提供单例模式支持,开发人员不再需要自己编写实现代码。 容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。 2.源码架构 1.核心容器(Core Container): Spring-beans和Spring-core模块是 Spring 框架的核心模块,包含控制反转(Inversion of Control, IoC)和依赖注入(Dependency Injection, DI),核心容器提供 Spring 框架的基本功能。 核心容器的主要组件是BeanFactory,工厂模式的实现。BeanFactory使用控制反转(IOC) 思想将应用程序的配置和依赖性规范与实际的应用程序代码分开。 Spring上下文Spring Context:Spring上下文是一个配置文件,向Spring框架提供上下文信息。 Spring-Expression模块是统一表达式语言(unified EL)的扩展模块,可以查询、管理运行中的对象,同时也方便的可以调用对象方法、操作数组、集合等。 2.Spring-AOP(Aspect Oriented Programming): Spring-aop是Spring的另一个核心模块, 在Spring中,他是以JVM的动态代理技术为基础,然后设计出了一系列的Aop横切实现。 通过其配置管理特性,Spring AOP模块直接将面向切面的编程功能集成到了Spring框架中。 3.Spring Data Access(数据访问): 由Spring-jdbc、Spring-tx、Spring-orm、Spring-jms和Spring-oxm 5个模块组成。 Spring-jdbc模块是Spring提供的JDBC抽象框架的主要实现模块,用于简化Spring JDBC。 Spring-tx模块是SpringJDBC事务控制实现模块。使用Spring框架,它对事务做了很好的封装,通过它的Aop配置,可以灵活的配置在任何一层。 Spring-Orm模块是ORM框架支持模块,主要集成 hibernate, Java Persistence API (JPA) 和 Java Data Objects (JDO) 用于资源管理、数据访问对象(DAO)的实现和事务策略。 Spring-Jms模块(Java Messaging Service)能够发送和接受信息。 Spring-Oxm模块主要提供一个抽象层以支撑OXM(OXM 是 Object-to-XML-Mapping的缩写,它是一个O/M-mapper,将java对象映射成 XML 数据,或者将XML数据映射成 java 对象)。 4.Web模块: 由Spring-web、Spring-webmvc、Spring-websocket和Spring-webmvc-portlet 4个模块组成。 Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。 5.报文发送: 即Spring-messaging模块。 Spring-messaging是Spring4新加入的一个模块,主要职责是为Spring 框架集成一些基础的报文传送应用。 6.单元测试: 即Spring-test模块。 Spring-test模块主要为测试提供支持。 3.环境搭建 环境要求 JDK版本:JDK 1.7 及以上版本。 Spring版本:Spring 5.x版本。 1.调整项目环境 1.修改JDK版本 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> 2.修改单元测试JUnit版本 <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> 3.build标签中的pluginManagement标签 <build> </build> 2.添加Spring框架的依赖坐标 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.4.RELEASE</version> </dependency> 3.编写Bean对象 public class UserService { public void test(){ System.out.println("Hello Spring!"); } } 4.添加Spring配置文件 1.在项目的src下创建文件夹resources(Alt+insert) 。 2.将resources标记为资源目录。 3.在src\main\resources目录下新建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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置bean对象 class:需要spring帮助创建实例对象的路径,权限定名 id:给实例化后对的别名,唯一的标识 --> <bean id="userService" class="com.xxxx.service.UserService">></bean> </beans> 5.加载配置文件,获取实例化对象 public class App { public static void main(String[] args) { //获取Spring上下文环境 (加载配置文件) //根据相对路径加载资源 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); // 通过getBean方法得到Spring容器中实例化好的Bean对象 (实例化Bean对象) // userService代表的是配置文件中bean标签的id属性值 UserService userService = (UserService) ac.getBean("userService"); // 调用方法 (使用实例化对象) userService.test(); } }
-
Spring IOC容器Bean对象实例化模拟
思路: 1.定义Bean工厂接口,提供获取bean方法。 2.定义Bean工厂接口实现类,解析配置文件,实例化Bean对象。 3.实现获取Bean方法。 1.定义Bean属性对象 bean对象:用来接收配置文件中bean标签的id与class属性值。 2.添加dom4j坐标依赖 <!-- dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> <!-- XPath --> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1.6</version> </dependency> 3.准备自定义配置文件 spring.xml: <?xml version="1.0" encoding="utf-8" ?> <beans> <bean id="userService" class="com.xxxx.service.UserService"></bean> <bean id="accountService" class="com.xxxx.service.AccountService"></bean> </beans> 4.定义Bean工厂接口 //通过id值获取对象 public Object getBean(String id); 5.定义Bean接口的实现类 模拟Spring的实现 1.通过构造器得到相关配置文件。 2.通过dom4j解析xml文件,得到List存放id和class 。 3.通过反射实例化得到对象 Class.forName(类的全路径).newInstance(); 通过Map<id,Class>存储 。 4.得到指定的实例化对象。 6.测试自定义IOC容器 1.创建与配置文件中对应的Bean对象。 2.测试是否可以获取实例化的Bean对象。
-
Spring IOC容器Bean对象实例化
1.构造器实例化 1.设置配置文件spring.xml。 <bean id="userService" class="com.xxxx.service.UserService"></bean> 2.获取实例化对象。 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.test(); 注意:通过默认构造器创建,空构造方法必须存在,否则创建失败。 2.静态工厂实例化 1.定义静态工厂类。 2.设置配置文件spring.xml。 3.获取实例化对象。 注意:要有该工厂类及工厂方法,工厂方法为静态的。 3.实例化工厂实例化 1.定义工厂类。 2.设置配置文件spring.xml。 3.获取实例化对象。 注意:工厂方法为非静态方法,需要配置工厂bean,并在业务bean中配置factory-bean,factory-method属性。 Spring三种实例化Bean的方式比较 1.通过bean的缺省构造函数创建,当各个bean的业务逻辑相互比较独立的时候或者和外界关联较少的时候可以使用。 2.利用静态factory方法创建,可以统一管理各个bean的创建,如各个bean在创建之前需要相同的初始化处理,则可用这个factory方法险进行统一的处理等等。 3.利用实例化factory方法创建,即将factory方法也作为了业务bean来控制,既可用于集成其他框架的bean创建管理方法,也能够使bean和factory的角色互换。
-
Spring IOC注入
1.手动装配(注入)(推荐使用) 1.set方法注入 1.属性字段提供set方法。 2.配置文件的bean标签设置property标签。 IOC通过property标签手动装配(注入): name:bean对象中属性字段的名称 。 ref:指定bean标签的id属性值。(业务对象、JavaBean) value:具体的值。(基本类型、常用对象|集合类型、属性对象) 2.构造器注入(提供带参构造器) 1.提供构造器。 2.配置文件的bean标签设置constructor-arg标签。 IOC通过通过constructor-arg标签手动装配(注入): name:属性名称。 ref:指定bean标签的id属性值。(JavaBean) value:具体的值 。(基本类型、常用对象) index:构造器中参数的下标,从0开始。 循环依赖问题 原因:Bean通过构造器注入,之间彼此相互依赖对方导致bean无法实例化。 解决:将构造器注入改为set方法注入。 3.静态工厂注入 1.定义静态工厂类。 2.Java代码。 3.在配置文件中设置bean标签,指定工厂对象并设置对应的方法。 注意:静态工厂注入也是借助set方法注入,只是被注入的bean对象的实例化是通过静态工厂实例化的。 4.实例化工厂注入 1.定义工厂类。 2.Java代码。 3.在配置文件中声明工厂bean标签,声明bean对象,指明工厂对象和工厂方法。 注意:实例化工厂注入也是借助set方法注入,只是被注入的bean对象的实例化是通过实例化工厂实例化的。 p名称空间的使用 spring2.5以后,为了简化setter方法属性注入,引用p名称空间的概念,可以将子元素,简化为元素属性配置。 1.属性字段提供set方法。 2.在配置文件spring.xml引入p名称空间。 xmlns:p="http://www.springframework.org/schema/p" p:属性名:="xxx" 引入常量值 p:属性名-ref:="xxx" 引入其他Bean对象的id属性值 2.自动装配(注入) 注解方式注入Bean(通过反射技术实现) 准备环境: 1.修改配置文件 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 2.开启自动化注入 <context:annotation-config/> 3.给注入的bean对象添加注解 @Resource注解 默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等) 如果属性字段名称未找到,则会通过类型(Class类型)查找 注意: 1.属性可以提供set方法,也可以不提供set方法。 2.注解可以声明在属性级别或set方法级别。 3.可以设置name属性,name属性值必须与bean标签的id属性值一致。 如果设置了name属性值,就只会按照name属性值查找bean对象。 4.当注入接口时,如果接口只有一个实现则正常实例化。 如果接口存在多个实现,则需要使用name 属性指定需要被实例化的bean对象。 @Autowired注解 默认通过类型(Class类型)查找bean对象,与属性字段的名称无关 注意: 1.属性可以提供set方法,也可以不提供set方法。 2.注解可以声明在属性级别或set方法级别。 3.可以添加@Qualifier结合使用,通过value属性值查找bean对象(value属性值必须要设置,且值要与bean标签的id属性值对应)。 推荐使用@Resource注解是属于J2EE的,减少了与Spring的耦合。
-
Spring IOC扫描器
作用:bean对象统一进行管理,简化开发配置,提高开发效率。 <context:component-scan base-package="com.xxxx"></context:component-scan> 1.设置自动化扫描的范围 如果bean对象未在指定包范围,即使声明了注解,也无法实例化 2.使用指定的注解(声明在类级别) bean对象的id属性默认是类的首字母小写 Dao层 @Repository Service层 @Service Controller层 @Controller 任意类 @Component 注意:开发过程中建议按照指定规则声明注解。
-
Bean的作用域与生命周期
1.作用域 默认情况下,我们从Spring容器中拿到的对象均是单例的,对于bean的作用域类型如下: 1.singleton作用域 <bean id="" class="" lazy-init=""></bean> lazy-init属性(懒加载) 如果为false,则在IOC容器启动时会实例化bean对象,默认false。 如果为true,则IOC容器启动时不会实例化Bean对象,在使用bean对象时才会实例化。 lazy-init设置为false的好处: 1.可以提前发现潜在的配置问题。 2.Bean对象存在于缓存中,使用时不用再去实例化bean,加快程序运行效率。 单例对象: 一般来说对于无状态或状态不可改变的对象适合使用单例模式。(不存在会改变对象状态的成员变量) 比如:controller层、service层、dao层 无状态或状态不可改变的对象: 实际上对象状态的变化往往均是由于属性值得变化而引起的。 对于我们的程序来说,无状态对象没有实例变量的存在,保证了线程的安全性,service 层业务对象即是无状态对象。线程安全的。 2.prototype作用域 <bean id="" class="" scope=""></bean> 通过scope="prototype" 设置bean的类型 ,每次向Spring容器请求获取Bean都返回一个全新的Bean。 相对于scope="singleton"来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean。 3.Web应用中的作用域 1.request作用域 表示每个请求需要容器创建一个全新Bean。比如提交表单的数据必须是对每次请求新建一个Bean来保持这些表单数据,请求结束释放这些数据。 2.session作用域 表示每个会话需要容器创建一个全新Bean。比如对于每个用户一般会有一个会话,该用户的用户信息需要存储到会话中,此时可以将该Bean作用域配置为session级别。 3.globalSession作用域 类似于session作用域,其用于portlet(Portlet是基于Java的Web组件,由Portlet容器管理,并由容器处理请求,生产动态内容)环境的web应用。如果在非portlet环境将视为session作用域。 2.生命周期 在Spring中,Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段。 1.Bean的定义 在Spring中,通常是通过配置文档的方式来定义Bean的。 在一个配置文档中,可以定义多个Bean。 2.Bean的初始化 默认在IOC容器加载时,实例化对象。 1.在配置文档中通过指定init-method属性来完成。 <bean id="roleService" class="com.yjxxt.service.RoleService" init-method="init"> </bean> 2.实现org.springframework.beans.factory.InitializingBean接口。 注意:Bean对象实例化过程是在Spring容器初始化时被实例化的,但也不是不可改变的, 可以通过lazy-init="true"属性延迟bean对象的初始化操作,此时再调用getBean方法时才会进行bean的初始化操作。 3.Bean的使用 1.使用BeanFactory。 //得到Spring的上下文环境 BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml"); RoleService roleService = (RoleService) factory.getBean("roleService"); 2.使用ApplicationContext。 //得到Spring的上下文环境 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); RoleService roleService = (RoleService) ac.getBean("roleService"); 3.Bean的销毁 步骤: 1.实现销毁方式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执行的方法)。 <bean id="roleService" class="com.yjxxt.service.RoleService" destroy- method="destroy"></bean> 2.通过AbstractApplicationContext对象,调用其close方法实现bean的销毁过程。 AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml"); ctx.close();