Spring
- Spring的概述
- Spring的入门
什么是spring框架?
- Spring是一个开源框架
- Spring为简化企业级应用开发而生。使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能
- Spring使javaSE/JavaEE的一站式框架
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
Spring的优点
- 方便解耦,简化开发
- spring就是个大工厂,将所有对象创建和依赖关系维护,交给Spring管理
- AOP编程的支持
- Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
- 声明式事务的支持
- 只需要通过配置就可以完成对事务的管理,而且无需手动编程
- 方便程序测试
- Spring对junit4支持,可以用过注解方便的测试Spring程序
- 方便集成各种优秀框架
- Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibertnate、MyBatis等)的直接支持
- 降低JavaEE API的使用难度
- Spring对JavaEE开发中非常难用的一些API(JDBC、Javamail、远程调用等),都提供了封装,使这些API应用难度大大降低
Spring IOC的底层原理实现
传统方式的开发
UserService us=new UserService();
↓ 面向接口编程
UserService us=new UserSerivceImpl();
↓ ocp原则:open-close 原则,对程序拓展是open的,对修改程序代码是close
↓ 尽量做到不修改程序的源码,实现对程序的扩展
工厂模式
工厂类创建 示例对象
class FactoryBean{
public static UserService getUs(){
return new UserServiceImpl();
}
}
UserService us=FactoryBean.getUs();
工厂+反射+配置文件
<bean id="us" class="com.imooc.UserServiceImpl"/>
class FactoryBean{
public static Object getBean(String id){
...
反射
}
}
Spring IOC的快速入门案例
下载Spring开发包
https://repo.spring.io/libs-release-local/org/springframework/spring/
复制Spring开发jar包到工程
理解IOC控制反转和DI依赖注入
编写Spring核心配置文件
在程序中读取Spring配置文件,通过Spring框架获得Bean,完成相应操作
创建Maven工程
pom.xml
spring相关依赖
spring-core/spring-context/spring-beans/spring-logging
<?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>sipc</groupId> <artifactId>food</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>food Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.1.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.1.8.RELEASE</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <build> <finalName>food</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
创建applicationContext.xml
创建接口
继承接口
SpringDemo1
package ioc.demo1;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo1 {
@Test
public void demo1(){
UserService userService=new UserServiceImpl();
userService.sayHello();
}
@Test
// spring的方式实现
public void demo2(){
//创建Spring的工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(“applicationContext.xml”);
//通过工厂获得类
UserService userService=(UserService) applicationContext.getBean(“userService”);
userService.sayHello();
}
}
### IOC和DI的概念
- IOC Inverse of Control 反转控制的概念,就是将原本在程序中手动创建UserService对象的控制权,交由
Spring框架处理
- 简单说,就是创建UserService对象控制权被反转到了Spring框架
- DI Dependency Injection 依赖注入的概念,就是在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">
<!--UserService的创建权交给了Spring-->
<bean id="userService" class="ioc.demo1.UserServiceImpl">
<!--控制反转-->
<!--设置属性-->
<property name="name" value="李四"/>
<!--依赖注入-->
</bean>
</beans>
Spring Bean管理
三种实例化Bean的方式
使用类构造器实例化(默认无参数)
- 创建java/demo2/Bean1
package demo2; //实例化的三种方式:采用无参数的构造方法的参数 public class Bean1 { public Bean1(){ } }
- 配置spring config applicationContext.xml
<bean id="bean1" class="demo2.Bean1"/>
3. SpringDemo2中(测试)
package demo2; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringDemo2 { @Test public void demo1(){ //创建工厂 ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); //通过工厂获得类的实例 Bean1 bean1= (Bean1) applicationContext.getBean("bean1"); } }
使用静态工厂方法实例化(简单工厂模式)
- 创建java/demo2/Bean2
package demo2; //静态工厂实例化方式 public class Bean2 { }
- 创建demo2/Bean2Factory
package demo2; public class Bean2Factory { //第二种:Bean2的静态工厂 public static Bean2 createBean2(){ System.out.println("Bean2Factory的方法已经执行了"); return new Bean2(); } }
3. applicationContext.xml
```xml
<bean id="bean2" class="demo2.Bean2Factory" factory-method="createBean2"/>
```
4. SpringDemo2中(包含bean3)
```java
package demo2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo2 {
@Test
public void demo1(){
//创建工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Bean1 bean1= (Bean1) applicationContext.getBean("bean1");
}
public void demo2(){
//创建工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Bean2 bean2= (Bean2) applicationContext.getBean("bean2");
}
public void demo3(){
//创建工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Bean3 bean3= (Bean3) applicationContext.getBean("bean3");
}
}
- 使用实例工厂方法实例化(工厂方法模式)
- java/demo2/Bean3
package demo2;
//第三种:实例工厂实例化的方式
public class Bean3 {
}
- demo2/Bean3Factory
package demo2;
public class Bean3Factory {
public Bean3 createBean3(){
System.out.println("Bean3Factory被执行了");
return new Bean3();
}
}
- applicationContext.xml
<bean id="bean3Factory" class="demo2.Bean3Factory"/>
<bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"/>
- SpringDemo2
package demo2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo2 {
@Test
public void demo1(){
//创建工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Bean1 bean1= (Bean1) applicationContext.getBean("bean1");
}
public void demo2(){
//创建工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Bean2 bean2= (Bean2) applicationContext.getBean("bean2");
}
public void demo3(){
//创建工厂
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过工厂获得类的实例
Bean3 bean3= (Bean3) applicationContext.getBean("bean3");
}
}
Bean的配置
- id和name
- 一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称
- id 属性在IOC容器中必须是唯一的
- 如果Bean的名称中含有特殊字符,就需要使用name属性
- class
- class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例
Bean的作用域
类别 | 说明 |
---|---|
singleton | 在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存在 |
prototype | 每次调用getBean()时都会返回一个新的实例 |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean,该作用域仅适用于WebApplicationContext环境 |
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的作用范围-->
<bean id="person" class="com.majiajun.demo3.Person" scope="prototype"/>
</beans>
demo3/Person
package com.majiajun.demo3;
public class Person {
}
demo3/SpringDemo3
package com.majiajun.demo3;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*Bean作用范围的测试*/
public class SpringDemo3 {
@Test
public void demo1(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Person person= (Person) applicationContext.getBean("person");
Person person1=(Person) applicationContext.getBean("person");
System.out.println(person);
System.out.println(person1);
}
}
Bean的生命周期
<bean id="man" class="demo3.Man" init-method="setup" destroy-method="teardown"></bean>
Bean的生命周期的完整过程
instantiate bean对象实例化
public class Man(){ public Man(){ System.out.println("第一步:对象的实例化"); } }
poprlate properties封装属性
public class Man{ private String name; public void setName(String name) { System.out.println("第二步:设置属性"); this.name = name; }
如果Bean实现BeanNameAware执行setBeanName
如果Bean实现BeanFactoryAware或者ApplicationContextAware设置工厂 setBeanFactory或者上下文对象setApplicationContext
public class Man implements BeanNameAware, ApplicationContextAware { private String name; public void setName(String name) { System.out.println("设置属性"); this.name = name; } public Man(){ System.out.println("Man被实例化"); } public void setup(){ System.out.println("Man被初始化"); } public void teardown(){ System.out.println("Man被销毁了"); } @Override public void setBeanName(String s) { System.out.println("第三步:设置Bean的"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("第四步:了解工厂的信息"); } }
如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization
package com.majiajun.demo3; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("第五步:初始化前方法"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("第八步:初始化后方法"); return bean; } }
如果Bean实现InitializingBean执行afterPropertiesSet
package com.majiajun.demo3; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class Man implements BeanNameAware, ApplicationContextAware, InitializingBean { private String name; public void setName(String name) { System.out.println("设置属性"); this.name = name; } public Man(){ System.out.println("Man被实例化"); } public void setup(){ System.out.println("Man被初始化"); } public void teardown(){ System.out.println("Man被销毁了"); } @Override public void setBeanName(String s) { System.out.println("第三步:设置Bean的"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("第四步:了解工厂的信息"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("第六步:属性设置后"); } }
调用
指定初始化方法init 如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessAfterInitialization
执行业务处理(自己定义的方法),如下
public class Man{ public void run(){ System.out.println("第九步:执行业务方法"); } }
如果Bean实现DisposableBean执行destory
public class Man implements DisposableBean{ public void destory()throws Exception{ System.out.println("第十步:执行Spring的销毁方法"); } }
调用
指定销毁方法customerDestory
Spring容器中Bean的生命周期
- 演示如何增强一个类中的方法
Spring的属性注入
对于类成员变量,注入方式有三种
- 构造函数注入
- 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用
- 属性settrt方法注入
- 接口注入
- 构造函数注入
Spring支持前两种
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!