week15_day02_Spring_IOCDIApplicationContextlombokxml文件中注册bean的方式生命周期

本文主要是介绍week15_day02_Spring_IOCDIApplicationContextlombokxml文件中注册bean的方式生命周期,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

总结昨天的内容:

  1. 设计模式
    最佳实践(经验)

  2. 特点
    s:单一职责
    o:开闭原则
    l:里氏替代原则
    i:接口隔离
    d:依赖倒置

  3. 具体的设计模式

3.1单例(重要)
应用程序对应的实例只有一个

1、构造方法私有
2、包含自己的成员变量
3、提供静态方法给其他人调用

线程不安全的懒加载(在方法上开始初始化的)
线程安全的懒加载(在方法上开始初始化的,并且在方法上加锁sync)
线程安全的立即加载(在静态成员变量上直接初始化)
线程安全的立即加载(在静态代码块中初始化)
线程安全的懒加载(静态内部类实现,当你调用到静态内部类的方法的时候,静态内部类才加载) → 将实例初始化的过程放在了静态内部类中

3.2工厂

3.2.1简单工厂
给工厂方法的形参中 给不同的值,生产出的实例有所不同
当需要新的生产实例的时候,需要去修改工厂的生产方法

3.2.2工厂方法
更好的满足了开闭原则
提供一个工厂接口,提供生产方法的规范

具体的工厂实现工厂接口,在具体的工厂中提供详细的生产方法

3.2.3使用方式

3.2.3.1实例工厂
工厂中的生产方法非静态方法
先对工厂进行实例化,然后通过工厂对象来调用生产方法

3.2.3.2静态工厂
工厂中的方法是静态方法,可以直接调用。静态工厂类似于工具类。

3.3代理(非常重要)
给委托类实现原有的功能的基础上,并且进行增强

3.3.1静态代理

3.3.1.1委托类成员变量
委托类以代理类中的成员变量的形式存在,可以调用委托类对象的方法
在HouseProxy中定义了一个HouseOwner的成员变量

3.3.1.2代理类继承委托类
重写父类(委托类)的方法,并且在重写的方法中调用父类的方法(super来调用)

3.3.2动态代理
都是要获得一个代理对象,通过代理对象调用的方法才是增强的方法

3.3.2.1jdk动态代理
类要有接口的实现,生成的代理对象和接口相关。并且要用接口来接收。

HelloService helloService = new HelloServiceImpl();
Object proxy = Proxy.newProxyInstance(classloader,interfaces,new InvocationHandler(){public Object invoke(proxy,method,args){//前面的增强Object object = method.invoke(helloSerivce,args);//后面的增强return object;
}
});

Object proxy只能用接口来接收,不能用实现类。

3.3.2.2cglib动态代理

invocationHandler和jdk动态代理的invocationHandler是不同包下的,不是同一个
Object proxy = Enhancer.create(class,new InvocationHandler(){public Object invoke(proxy,method,args){//前面的增强Object object = method.invoke(helloSerivce,args);//后面的增强return object;
}
});

Object proxy可以用接口也可以用实现类来接收。
因为cglib的实现是用代理类继承委托类。根据里氏替换原则,可以用父类接收子类。

3.4建造者builder
更侧重于设置参数的过程

在builder中 在创建builder时(生产之前)已经完成了实例化
需要保证始终对同一个实例设置参数,实例就要求是全局变量

set方法如果想要连续用起来,要求这些set方法的返回值为builder
.setHeadIq(120).setHeadEq(120).setLegLength()


Spring介绍(4天)
SpringIOC
SpringAOP
Spring事务


Spring 概念
Spring框架其实就是偏基础性的框架。可以去整合其他框架。类似于平台。
核心:IOC、DI和AOP

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。
它是为了解决企业应用开发(JavaEE)的复杂性而创建的。框架的主要优势之一就是其分层架构(MVC分层),分层架构允许使用者选择使用哪一个组件,同时为 J2EE(JavaEE) 应用程序开发提供集成的框架。
Spring是一个分层的Java SE/EE full-stack(一站式) 轻量级开源框架。


IOC&DI

IOC用于实例化类对象,管理类对象
IOC:Inverse of Controll 控制反转
控制:实例的生成权
反转:由应用程序反转给spring
容器:容器是放置实例对象的地方 → Spring容器、IOC容器

原先实例我们想用的时候自己new出来(主动的过程);到了Spring阶段,把实例的生成权交给了Spring容器,由Spring容器进行生成并管理,当我们想用的时候就从容器中取出来。

例子:小明挣了10块钱自己花。
小明找到了对象,挣的10块钱交给了对象。小明想花5毛,就要跟对象申请。

所谓IOC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

DI:Dependency Injection 依赖注入
应用程序(贫穷) ←→ Spring容器(富有)
经过了控制反转,谁富有谁贫穷
依赖:
谁依赖谁? 小张依赖他对象 → 应用程序依赖Spring容器
为什么依赖? 小张对象有钱 → Spring容器包含了应用程序必须的内容
注入
谁注入谁? Spring容器注入给应用程序
注入了什么?应用程序运行所必须的资源

谁依赖了谁:应用程序依赖于IOC容器
为什么要依赖:应用程序需要IOC容器来提供对象需要的外部资源
谁注入谁:IOC容器注入应用程序某个对象,应用程序依赖的对象
注入了什么:注入某个对象所需要的外部资源(包括对象、资源、常量数据)
在这里插入图片描述


aop:面向切面编程→ aspect oriented programming
oop→ object oriented programming


Spring Introduction
在这里插入图片描述
声明式事务支持:指定方法增加事务 → 通过注解指定方法 → 指哪儿打哪儿
事务 → 保证使用的是同一个connection → aop阶段会布置对应的作业

Spring的单元测试 → 提供了Spring环境


Spring 特点:
Core technologies: dependency injection, events, resources, i18n, validation, data binding, type conversion, SpEL, AOP.
依赖注入、资源、i18n国际化(springmvc)、校验(Springmvc)、数据绑定、类型转换(springmvc)、SpringExpressionLanguage、Aop(面向切面编程)
在这里插入图片描述


Spring Framework:
在这里插入图片描述

Core Container是Spring的核心组件。Spring的核心依赖就在这。
Spring的核心依赖:5+1
spring-core、spring-context、spring-aop、spring-beans、spring-expression
commons-logging(jcl)


写一个入门案例:

  1. 导入相关依赖:
    在这里插入图片描述
  2. 定义一个service
package com.cskaoyan.service;public class HelloService {public void sayHello(String name) {System.out.println("hello " + name);}
}

想要通过Spring容器管理HelloService对象,就得先创建一个Spring容器。

  1. 创建Spring容器

通过Spring配置文件来管理组件
xml的文件 → 通常名字叫application(-xx).xml
既然是xml文件,文件要满足一定的约束(schema),约束就是规定你书写的格式是什么样的。

约束怎么来?
1、复制已有的配置文件的约束
2、从spring的参考文档上的appendix上复制
3、通过创建文件模板来使用 (推荐)效率高

第一次学习,我们只能通过第二种方式来使用。
在这里插入图片描述
有了第一次后,后面再创建Spring配置文件就用第三种方式:
那么,如何创建文件模板?
a. 创建
在这里插入图片描述
在这里插入图片描述
b. 使用模板
选择自己创建的模板
在这里插入图片描述
在这里插入图片描述
4. 将组件交给spring管理
组件:交给spring容器管理的实例,我们称之为组件
注册:在spring的配置文件中如何定义实例
HelloService交给Spring管理,这个过程叫做注册
在这里插入图片描述
将控制权反转也是通过反射技术来实现的。Spring通过class就能生产处这个类的实例对象。

  1. 从容器中取出实例进行使用
    locTest:
package com.cskaoyan;import com.cskaoyan.service.HelloService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 入门案例1*/
public class IocTest {@Testpublic void mytest1(){//初始化一个应用上下文,应用上下文是Spring容器一个高级功能的实现//再看ClassPath,表示类加载路径ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");//通过应用上下文从Spring容器中取出组件(实例)HelloService helloSerivce = (HelloService) applicationContext.getBean("helloSerivce");helloSerivce.sayHello("ligenli");}
}

这段代码中用到了ClassPath,下面就来讲一下classpath(类加载路径)。

a. maven的classpath
maven是根据文件夹名和目录结构来决定classpath

--src--main--java--resources

java和resources是maven项目的classpath

4.2idea中的classpath
应用要在idea中跑起来
在这里插入图片描述
在这里插入图片描述


locTest:

package com.cskaoyan;import com.cskaoyan.service.HelloService;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** 入门案例1*/
public class IocTest {@Testpublic void mytest1() {//初始化一个应用上下文,应用上下文是Spring容器一个高级功能的实现//再看ClassPath,表示类加载路径ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");//通过应用上下文从Spring容器中取出组件(实例)HelloService helloService = (HelloService) applicationContext.getBean("helloService");helloService.sayHello("ligenli");// 1、指定id获得实例对象// 2、指定类型(class)获得实例对象// 3、1+2,即指定id和class//条件:这个类型(class)的组件在容器中只有这一个HelloService helloService2 = (HelloService) applicationContext.getBean(HelloService.class);helloService2.sayHello("加油吧!");HelloService helloService3 = applicationContext.getBean("helloService", HelloService.class);helloService3.sayHello("just be you");}@Testpublic void mytest2(){ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");//从容器中,取出指定id的组件多次,看是否是同一个组件Object helloService = applicationContext.getBean("helloService");Object helloService2 = applicationContext.getBean("helloService");Object helloService3 = applicationContext.getBean("helloService");Object helloService4 = applicationContext.getBean("helloService");Object helloService1 = applicationContext.getBean("helloService");Assert.assertEquals(helloService,helloService2);}
}

在这里插入图片描述


入门案例2
也是通过spring容器管理组件;
管理多个组件 → 多个组件之间有依赖关系
HelloService依赖于HelloDao → 在Spring容器中如何维护多个组件之间的关系

  1. 导包
  2. 构建业务代码

HelloDao :

package com.cskaoyan.dao;public interface HelloDao {public void daoSayHello(String name);
}

HelloDaoImpl :

package com.cskaoyan.dao;public class HelloDaoImpl implements HelloDao{@Overridepublic void daoSayHello(String name) {System.out.println("hello " + name);}
}

HelloService :

package com.cskaoyan.service;public interface HelloService {public void sayHello(String name);
}

HelloServiceImpl :

package com.cskaoyan.service;import com.cskaoyan.dao.HelloDao;
import com.cskaoyan.dao.HelloDaoImpl;public class HelloServiceImpl implements HelloService{//我们自己不实例化对象,让Spring来帮我们实例化//HelloDao helloDao = new HelloDaoImpl();HelloDao helloDao;@Overridepublic void sayHello(String name) {helloDao.daoSayHello(name);}public HelloDao getHelloDao() {return helloDao;}public void setHelloDao(HelloDao helloDao) {this.helloDao = helloDao;}
}
  1. 注册组件并维护组件之间的关系
    在这里插入图片描述
    不能写接口,因为Spring管理组件的底层是通过反射实现的,给一个接口,如何实例化出对象呢?
    在这里插入图片描述
  2. 使用
package com.cskaoyan;import com.cskaoyan.dao.HelloDao;
import com.cskaoyan.service.HelloService;
import com.cskaoyan.service.HelloServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {@Testpublic void mytest(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");//HelloServiceImpl bean = applicationContext.getBean(HelloServiceImpl.class);//spring建议通过接口的类型取出,更容易规范你能去做的事情//比如给spring的组件增强,比如使用jdk动态代理的方式进行增强,那么增强后的组件和接口是相关联的HelloService helloService = applicationContext.getBean(HelloService.class);helloService.sayHello("songge");}@Testpublic void mytest2(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");HelloService helloService = applicationContext.getBean(HelloService.class);helloService.sayHello("songge");HelloDao helloDao = applicationContext.getBean(HelloDao.class);System.out.println(111);}
}

总结:Spring在这里有没有带来新的功能?并没有
调用的都是原有的方法sayHello和daoSayHello
但是提高了组件的重用频率
类似于搭积木,你需要什么样子的,就从容器中取出来。

学习了IOC 和 DI 最大的感触是什么?
控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法
依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。


Spring 核心API:

ApplicationContextClassPathXmlApplicationContextFileSystemXmlApplicationContext

在这里插入图片描述
都是去加载application
ClasspathXmlApplicationContext 加载classpath目录下的配置文件
FileSystemXmlApplicationContext 加载文件系统目录下的配置文件

package com.cskaoyan;import com.cskaoyan.service.HelloService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;public class MyTest {@Testpublic void mytest(){//从classpath加载配置文件→ java或resources目录ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");HelloService bean = applicationContext.getBean(HelloService.class);}@Testpublic void mytest2(){//D:\WorkSpace\j22_workspace\codes\day02-spring-ioc\demo3-applicationContext\src\main\resources\application.xmlString fileSystemPath = "D:\\WorkSpace\\j22_workspace\\codes\\day02-spring-ioc\\" +"demo3-applicationContext\\src\\main\\resources\\application.xml";ApplicationContext applicationContext = new FileSystemXmlApplicationContext(fileSystemPath);}
}

BeanFactory
在这里插入图片描述
在这里插入图片描述
BeanFactory:容器中所有的组件都是通过这个Bean生产出来的

BeanFactory:生产所有组件bean
FactoryBean:XXXFactoryBean,factoryBean对应的特定的xxx实例。即生产特定的Bean。


讲一个辅助编译的工具:Lombok
帮我们生成getter、setting、equal、hashcode、toString、有参无参构造方法
使用起来非常简单

  1. 引入依赖
    在这里插入图片描述
  2. 安装插件
    避免一些编译报错
    在这里插入图片描述
    可以选择离线下载
    在这里插入图片描述
  3. 使用lombok
    在这里插入图片描述
    会发现字节码文件中是这样的:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.cskaoyan.component;public class NoArgsConstructorBean {String name;Integer id;public NoArgsConstructorBean() {}public String getName() {return this.name;}public Integer getId() {return this.id;}public void setName(String name) {this.name = name;}public void setId(Integer id) {this.id = id;}public boolean equals(Object o) {if (o == this) {return true;} else if (!(o instanceof NoArgsConstructorBean)) {return false;} else {NoArgsConstructorBean other = (NoArgsConstructorBean)o;if (!other.canEqual(this)) {return false;} else {Object this$name = this.getName();Object other$name = other.getName();if (this$name == null) {if (other$name != null) {return false;}} else if (!this$name.equals(other$name)) {return false;}Object this$id = this.getId();Object other$id = other.getId();if (this$id == null) {if (other$id != null) {return false;}} else if (!this$id.equals(other$id)) {return false;}return true;}}}protected boolean canEqual(Object other) {return other instanceof NoArgsConstructorBean;}public int hashCode() {int PRIME = true;int result = 1;Object $name = this.getName();int result = result * 59 + ($name == null ? 43 : $name.hashCode());Object $id = this.getId();result = result * 59 + ($id == null ? 43 : $id.hashCode());return result;}public String toString() {return "NoArgsConstructorBean(name=" + this.getName() + ", id=" + this.getId() + ")";}
}

在这里插入图片描述
通常@AllArgsConstructor和@NoArgsConstructor同时出现
因为增加了有参构造方法会覆盖掉默认的无参构造方法,后续使用框架里底层很多用到反射,反射又经常使用到无参构造方法,通常需要额外增加@NoArgsConstructor


xml文件中注册bean的方式

构造方法
无参构造(最常用)
因为默认提供的是无参构造,这个是最常用

NoArgsConstructorBean :

package com.cskaoyan.component;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 无参构造方法* 默认包含无参的构造方法*/
@Data
@NoArgsConstructor
public class NoArgsConstructorBean {String name;Integer id;
}

在application.xml中的配置:
在这里插入图片描述

有参构造:

HasArgsConstructorBean :

package com.cskaoyan.component;import lombok.AllArgsConstructor;
import lombok.Data;/*** 有参构造方法*/
@AllArgsConstructor //写了有参构造方法,会将默认的无参构造方法覆盖掉
@Data
public class HasArgsConstructorBean {String name;Integer id;//public HasArgsConstructorBean(String name, Integer id) {//    this.name = name;//    this.id = id;//}
}

在application.xml中的配置:
在这里插入图片描述


工厂
通常是整合已有代码的时候,可以使用工厂注册组件(比如你写了一个工具类)
在这里插入图片描述
实例工厂:
在这里插入图片描述
静态工厂:
在这里插入图片描述


生命周期:

Spring中bean的生命周期
并不是所有的bean都会执行完所有的声明周期。
默认只会执行到1和2。之后这些需要满足一定的条件才能执行到。
6和9做的事情很类似,只不过和7、8之间有一个顺序关系。

在这里插入图片描述
默认是不会执行红框框中的生命周期的,只有实现了这些接口才会执行。

在这里插入图片描述
LifeCycleBean代码:
在这里插入图片描述

CustomBeanPostProcessor代码:
在这里插入图片描述
测试代码:

package com.cskaoyan.bean;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class LifeCycleTest {@Testpublic void mytest1(){//执行完这行代码就意味着组件可以使用了,也就是1-9的生命周期都执行完了ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");//不需要取出组件,生命周期就已经开始//关闭上下文后就会执行10、11生命周期applicationContext.close();}
}

执行结果:
在这里插入图片描述
可以利用生命周期的先后顺序写一些简单的业务逻辑。


作业:使用spring为项目里的所有类的所有方法增加
写几个不同的bean ,每个bean里包含不同的方法。
通过spring 使得调用任何一个实现方法之前和之后都增加一些内容输出。(通过PostBeanProcessor实现)
提示:生命周期 动态代理
提示:狸猫换太子

举个例子:比如有几个类Cat、Dog、Tiger,这几个类中分别有miao、wang、wuuu这几个方法,那么从容器中取出组件,调用这几个方法的时候(注意不是容器初始化时),miao、wang、wuuu这几个方法执行之前都会输出hello,执行之后都会输出world

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这篇关于week15_day02_Spring_IOCDIApplicationContextlombokxml文件中注册bean的方式生命周期的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/451319

相关文章

Spring IOC的三种实现方式详解

《SpringIOC的三种实现方式详解》:本文主要介绍SpringIOC的三种实现方式,在Spring框架中,IOC通过依赖注入来实现,而依赖注入主要有三种实现方式,构造器注入、Setter注入... 目录1. 构造器注入(Cons编程tructor Injection)2. Setter注入(Setter

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Spring IOC控制反转的实现解析

《SpringIOC控制反转的实现解析》:本文主要介绍SpringIOC控制反转的实现,IOC是Spring的核心思想之一,它通过将对象的创建、依赖注入和生命周期管理交给容器来实现解耦,使开发者... 目录1. IOC的基本概念1.1 什么是IOC1.2 IOC与DI的关系2. IOC的设计目标3. IOC

Spring Boot统一异常拦截实践指南(最新推荐)

《SpringBoot统一异常拦截实践指南(最新推荐)》本文介绍了SpringBoot中统一异常处理的重要性及实现方案,包括使用`@ControllerAdvice`和`@ExceptionHand... 目录Spring Boot统一异常拦截实践指南一、为什么需要统一异常处理二、核心实现方案1. 基础组件

java中的HashSet与 == 和 equals的区别示例解析

《java中的HashSet与==和equals的区别示例解析》HashSet是Java中基于哈希表实现的集合类,特点包括:元素唯一、无序和可包含null,本文给大家介绍java中的HashSe... 目录什么是HashSetHashSet 的主要特点是HashSet 的常用方法hasSet存储为啥是无序的

IDEA运行spring项目时,控制台未出现的解决方案

《IDEA运行spring项目时,控制台未出现的解决方案》文章总结了在使用IDEA运行代码时,控制台未出现的问题和解决方案,问题可能是由于点击图标或重启IDEA后控制台仍未显示,解决方案提供了解决方法... 目录问题分析解决方案总结问题js使用IDEA,点击运行按钮,运行结束,但控制台未出现http://

解决Spring运行时报错:Consider defining a bean of type ‘xxx.xxx.xxx.Xxx‘ in your configuration

《解决Spring运行时报错:Considerdefiningabeanoftype‘xxx.xxx.xxx.Xxx‘inyourconfiguration》该文章主要讲述了在使用S... 目录问题分析解决方案总结问题Description:Parameter 0 of constructor in x

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内