Spring架构开荒
IOC 控制反转
Inversion of Control
控制反转 依赖注入
1 控制什么?
控制对象的创建以及销毁
2 反转什么?
将对象的控制权交给IOC容器
举例说明:
张三要回家
对象:
- 小明 人
- 车 奔驰 宝马
Audi.java
public class Audi{
public void start(){
System.out.println("Audi.start");
}
public void turnLeft(){
System.out.println("Audi.start");
}
public void trunRight(){
System.out.println("Audi.start");
}
public void stop(){
System.out.println("Audi.start");
}
}
传统方式
张三控制车辆的流程:
1 创建一辆车
Audi audi = new Audi();
2 控制车辆的启动 直行 左右转
audi.start();
audi.turnLeft();
audi.trunRight();
turn.stop();
3 销毁车辆
java的jcc组织垃圾回收处理掉
张三的其他需求
比如看电影
public void goMovice(){
public void start(){
System.out.println("Audi.start");
}
public void stop(){
System.out.println("Audi.start");
}
}
现在张三要换一辆Buick车
在Zhangsan.java当就需要全部更改
产生了高耦合性
改进方案 1
把车升级到张三的属性域里面
这样就降低了耦合度
public class ZhangSan {
Buick car = new Buick();
public void goHome(){
car.start();
car.turnRight();
car.turnLeft();
car.stop();
}
}
改进方案 2
接口Car
public interface Car {
public void start();
public void turnLeft();
public void turnRight();
public void stop();
}
奔驰车实现这个车的接口
public class Audi implements Car{
public void start(){
System.out.println("Audi.start");
}
在ZhangSan当中用构造方法传进去Car
private Car car;
public ZhangSan(Car car){
this.car = car;
}
到现在Car已经不用ZhangSan来创建了 由IOC来创建了
车辆的控制权完全交给了IOC
实现自己编写一个IOC的容器
约定
- 所有的Bean的生命周期交由IOC容器管理
- 所有被依赖的Bean通过构造方法执行注入
- 被依赖的Bean需要优先创建(创建张三前先创建奥迪)
所有被依赖的Bean通过构造方法执行注入
public HumanWithCar(Car car) {
this.car = car;
}
private Car car;
Class003Test.java//测试IOC容器
public class Class003Test {
private IoCConteainer ioCConteainer = new IoCConteainer();
@Before//创建bean
public void before(){
ioCConteainer.setBean(Audi.class, "Audi");
ioCConteainer.setBean(Buick.class, "Buick");
ioCConteainer.setBean(ZhangSan.class, "ZhangSan","Audi");
ioCConteainer.setBean(Lisi.class, "Lisi","Buick");
}
@Test//使用bean
public void test(){
Human ZhangSan = (Human) ioCConteainer.getBean("ZhangSan");
ZhangSan.goHome();
Human Lisi = (Human) ioCConteainer.getBean("Lisi");
Lisi.goHome();
}
}
Spring IOC入门
1 创建一个javabean
public class Bean{
public Bean(){
System.out.println("Bean.bean");
}
}
2 在pom中加入spring的依赖
spring-core
spring-context
3 在resources文件夹下建立一个spring.xml文件
//class = 1 中创建的Bean 并给一个唯一标示id
<bena class = "bean" class="com.imooc.spring.ioc.class004.Bean">
//测试
public class Class004Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml);
Bean bean = context.getBean("bean",Bean.class);
System.out.println("bean = " + bean);
}
}
实例化Bean方式
- 构造方法实例化
- 静态方法
- 实例方法
构造方法实例化
1 创建Bean.java
public class Bean {
public Bean(){
System.out.println("Bean.bean");
}
}
2 在spring.xml中配置bean
<bean class = "com.spring.ioc.class05.Bean1" id = "bean1"/>
3 在class005Test.java中实例
public class class005Test {
@Test
public void test(){
//取上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//通过context get一个Bean
Bean bean = context.getBean("bean", Bean.class);
System.out.println("bean = " + bean);
}
}
静态方法实例化
1 创建一个BeanFactory.java
通过BeanFactory的getBean方法实例化Bean
public class Bean2Factory {
public static Bean2 getBean2(){
return new Bean2();
}
}
2 spring.xml中进行配置
<bean class = "com.spring.ioc.Class05.Bean2Factroy"
factory-method = "getBean2" id = "bean2"/>
3 Class005Test.java
Bean2 bean2 = context.getBean("bena2", Bean2.class);
实例方法实例化Bean
1 创建一个Bean3Factory.java
通过BeanFactory的getBean方法实例化Bean
public class Bean3Factory {
public static Bean3 getBean3(){
return new Bean3();
}
}
2 spring.xml中进行配置
<bean class = "com.spring.ioc.Class05.Bean3" factory-bean = "bean3Factory"
factory-method = "getBean3" id = "bean3"/>
3 Class005Test.java
Bean3 bean3 = context.getBean("bean3",Bean3.class);
System.out.println("bean3 = " + bean3);
给Bean取一个别名
1 name属性
<bean class = "myspring.Bean" name ="bean1_1,bean1_2 " id = "bean1"/>
2 alias属性
<alias name = "bean1" alias="bean1_3,bean1_4"/>
测试
Bean1 bean1_1 = context.getBean("bean1_1",Bean1.class);
System.out.println("bean1_1 = " + bean1_1);
Bean1 bean1_2 = context.getBean("bean1_2",Bean1.class);
System.out.println("bean1_2 = " + bean1_2);
但是这些名字不同的都是同一个Bean
注入Bean的方式
- 构造方法注入Bean
- set方法注入Bean
- 集合类Bean的型注入
- List
- Set
- Map
- Propertise
- null值注入
- 注入时创建内部Bean
前期准备
AnotherBean.java
public class AnotherBean {
}
Bena.java
public class Bean {
private AnotherBean anotherBean;
private String string;
public AnotherBean getAnotherBean() {
return anotherBean;
}
public void setAnotherBean(AnotherBean anotherBean) {
this.anotherBean = anotherBean;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
构造方法注入Bean
在Bean.java中写入构造方法
public Bean(AnotherBean anotherBean, String string) {
this.anotherBean = anotherBean;
this.string = string;
}
spring.xml
//index:参数是构造方法中的第几个参数
//name:当前参数的参数名字
//type:参数的类型
//value: 给参数赋值 适合简单的数据类型 string integer double float
//ref:复杂数据类型赋值 对应anotherbean的id
<bean class = "com.example.controller.Bean" id = "bean">
<constructor-arg index="0" name = "anotherBean"
type="com.example.controller.AnotherBean"
ref="anotherBean"/>
<constructor-arg index="1" name="string"
type="java.lang.String"
value="aaaaa"/>
</bean>
简单写法
<bean class="com.example.controller.AnotherBean" id = "bean"
c:anotherBean-ref="bean1" c:string="ccccc"
p:anotherBean1-ref="bean1_1" P:string1="ddddd"
/>
<util:property name="anotherBean1" ref = "anotherBean"/>
<util:property name = "String1" value="ddddd"/>
set方法注入Bean
集合类型的Bean的注入
- list
- set
- map
- propertise
List
spring.xml
<util:property name = "stringList">
<list>
<value>aaaaa</value>
<value>ddddd</value>
</list>
</util:property>
<util:property>
<list>
<ref bean = "anotherBean"/>
<ref bean = "anotherBean"/>
</list>
</util:property>
<util:propertiy name="properties">
<prop key="aaaaa">bbbbb</prop>
</util:propertiy>
class005Test.java
Bean bean = context.getBean("bean",Bean.class);
System.out.println("bean.getStringList() = " + bean.getSring());
System.out.println("bean.getProperties() = " + bean.getProperties());
null注入
Bean.java
public AnotherBean getAnotherBean2() {
return anotherBean2;
}
public void setAnotherBean2(AnotherBean anotherBean2) {
this.anotherBean2 = anotherBean2;
}
private AnotherBean anotherBean2;
spring.xml
<util:properties name = "anotherBean2">
<null/>
</util:properties>
class005Test.java
System.out.println("bean.getAnotherBean2()" + bean.getAnotherBean2());
注入的时候创建内部Bean
<util:properties>
<bean class = "com.example.controller.AnotherBean"/>
</util:properties>
Bean的作用域的问题
-
Sinleton作用域
-
prototype作用域
-
Web环境作用域
- requset
- session
- application
- websocket
-
自定义作用域
- SimpleThreadScope作用域
Singleton作用域(单例模式)
右侧的Bean会通过Spring注入左侧三个Bean中 只会创建一个Bean
Bean.java
public class Bean {
public Beanb getBeanb() {
return beanb;
}
public void setBeanb(Beanb beanb) {
this.beanb = beanb;
}
private Beanb beanb;
@Override
public String toString() {
return "Bean{" +
"beanb=" + beanb +
'}';
}
}
spring.xml
<bean class = "com.example.controller.People.Beanb" id = "bean2"
scope="prototype"/>
<bean class = "com.example.controller.People.Bean" id = "bean"
scope="prototype">
<property name="beanb" ref="bean2"></property>
</bean>
public class Class007Test {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Beanb bean2_1 = context.getBean("Beanb",Beanb.class);
System.out.println("bean2_1 = " + bean2_1);
Beanb bean2_2 = context.getBean("bean2_2 = " + bean2_2);
System.out.println("bean2_2 = " bean2_2);
bean bean1 = context.getBean("bean",Bean.class);
System.out.println("bean = " + bean);
}
Prototype作用域(多例模式)
Web相关作用域
- requset作用域
- sessiong作用域
- applicatiton作用域
- websocker作用域(很少使用)
SpringWeb上下文环境
如果使用DispatcherServlet 不需要增加其他配置
web.xml
RequsetController.java
spring.xml
<bean class="com.spring.ioc.class08.RequestController"/>
<bean class="com.spring.ioc.class08.SessionController"/>
<bean class="com.spring.ioc.class08.ApplicationController"/>
每次刷新@contraller不变
<bean class="com.spring.ioc.class08.RequestController" scope = "requset"/>
<bean class="com.spring.ioc.class08.SessionController" scope = "requset"/>
<bean class="com.spring.ioc.class08.ApplicationController" scope = "requset"/>
每次刷新@contraller改变
回顾
- request:每个requset请求斗湖创建一个单独的实例
- session:每个session都会创建一个单独的实例
- application:每个servletContext都会创建一个单独的实例
- websocket:每个websocket链接都会创建一个单独实例
自定义作用域
- SimpleThreadScope作用域
MyScope.java
spring.xml
Bean的懒加载
Spring容器会在创建容器时提前初始化Singleton作用域的bean
但如果Bean被标记了lazy-init = “true”
那么该Bean只有在其被需要的时候才会初始化
只对singleton作用域的bean有效
多例模式不知道bean什么时候被实例化
单一的Bean需要懒加载
<bean class = "com.example.controller.People.Beanb" id = "bean2"
scope="singleton" lazy-init="true"/>
所有的bean需要懒加载
<beans default-lazy-init="true">
位所有的bean都设置默认的
Bean初始化及销毁逻辑处理
如果Bean实例化之后执行一些逻辑 有两种方法
- bean标签里的属性 initmethod
- 让Bean实现InitializingBean接口
如果Bean在销毁之前需要执行一些逻辑 两种方法
- destory-method
- DisposableBean接口
Bean属性继承
场景1
简化代码
场景2
注解
spring2.5之后用注解取代xml
xml 与 annotation对比
MyConfiguration.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfiguration {
@Bean //这里也可以用(value=“bean1命名”)
public Bean bean1(){
return new Bean();
}
}
Test.java
import com.example.controller.People.MyConfiguration;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Class008Test {
@Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
Bean1 bean1 = context.getBean("bean",Bean.class);
System.out.println("bean1 = " + bean1);
}
}
简化代码
conpoent-scan包扫描
@ component注解
给Bean取别名
通过注解注入Bean
构造方法和Set方法注入Bean
通过属性直接注入
实例化和注入时指定Bean的id
List/Set注入
直接注入List实例
将多个泛型实例注入到List
Map注入
多个泛型实例注入Map
String Integer类型的直接赋值
Spring Ioc容器内置借口实例注入
可以直接将ApplicationContext注入进来,也可以注入BeanFactory、Environment、ResourceLoader、ApplicationEventPublisher\MessagerSource及其实现类
SpringIoc注解设定Scope(作用域)
Spring预定义作用域
自定义作用域
方法注入
通过注解开启Bean的懒加载
通过注解编写Bean初始化及销毁
上一篇: PyCharm开荒
推荐阅读
-
Spring Cache的基本使用与实现原理详解
-
spring-boot整合ehcache实现缓存机制的方法
-
Spring @Bean vs @Service注解区别
-
详解Spring Cloud Hystrix断路器实现容错和降级
-
spring boot 即时重新启动(热更替)使用说明
-
使用 Spring Boot 2.0 + WebFlux 实现 RESTful API功能
-
spring boot2.0实现优雅停机的方法
-
struts2+spring+hibernate分页代码[比较多]第1/7页
-
浅谈Spring中@Transactional事务回滚及示例(附源码)
-
Spring实现上拉刷新和下拉加载效果