第一部分:核心容器

news2024/11/24 19:14:59

前言:学习路线

Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!

第一章:纯手写

一、核心概念

        什么是IoC、IoC容器、bean、DI ?

IoC:对象创建控制权由程序转移到IoC容器的控制反转思想。

IoC容器:创建管理对象的容器。

bean:IoC容器中被创建管理的对象。

DI:IoC容器中建立bean之间依赖关系的过程。

 

二、IoC入门实例

 第一步:在pom.xml添加spring-context依赖

第二步:在resources创建spring Config

只有成功添加了spring-context依赖才会显示出spring Config选项

 第三步:在spring config内 创建bean

第四步:初始化IoC容器,并获取bean

三、DI入门实例

 第一步:解耦&添加setter方法

 此setter方法是容器在调用,往service层传递对象

第二步:配置service与dao的关系

将dao注入到service

 四、bean基础配置

总:bean基础配置id 、class;别名name;作用范围scope。

bean别名配置

 在spring配置文件内依赖注入 ref时可以使用别名;在调用容器获取bean时也可以使用别名;

写id更规范。

bean的作用范围

通过直接打印调用容器内的对象的地址来判断获取的对象是同一个对象还是不同的对象。

bean的作用范围scope:控制我们创建实例的数量;

 五、bean实例化<4>

1、构造方法(常用)

bean本质是对象,创建bean使用构造方法完成。

spring创建bean调用的是无参构造方法。

spring报错,由下往上看。

无论我把无参构造方法调整位置,最终打印出来的首先就是无参构造方法里面打印的信息。说明spring在创建bean时是调用无参构造方法完成对象的创建和初始化。然后再调用实例化对象的方法。

 注意:如果未手写无参构造方法,会自动调用默认的无参构造方法。

但是如果手写了构造方法,无参的,则会优先调用手写的;如果手写了有参构造方法,也不会再调用默认的无参构造方法,但倘若没有另外手写无参构造方法,只能调用有参构造方法,会报错:NoSuchMethodException。此部分和java创建对象时的知识连起来的。

2、静态工厂(了解)

  • 调用静态工厂方法创建 bean 是将对象创建的过程封装到静态方法中 , 当客户端需要对象时 , 只需要简单地调用静态方法 , 而不需要关心创建对象的细节。
  • 要声明通过静态方法创建的 bean , 需要在 bean 的 class 属性里面指定拥有该工厂的方法的类 , 同时在 factory-method 属性里指定工厂方法的名称。最后 , 使用 <constructor-arg> 元素为该方法传递方法参数。
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        return new OrderDaoImpl();
    }
}
<bean id="orderdao" class="com.itheima.factory.OrderDaoFactory" 
      factory-method="getOrderDao"/>

3、实例工厂(了解)

实例工厂

public class UserDaoFactory {
    //注意此处采用非静态方法创建对象
    public UserDao getUserDao(){
        System.out.println("此处是调用非静态工厂创建对象的方法");
        return new UserDaoImpl();
    }
}

配置

 3、通过实例工厂创建对象 -->
<bean id="userdaofactory"
class="com.itheima.factory.UserDaoFactory"/>

<bean id="userdao" factory-method="getUserDao" 
factory-bean="userdaofactory"/>

弊端:要通过实例工厂对象的方法创建对象,在配置时需要多余配置无意义的bean。

4、Factory Bean(重要)

FactoryBean

//继承接口并且要填写范型-要造的对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //实现接口内的抽象方法(3个))
    //1、代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        System.out.println("此处调用factorybean方式创建对象");
        return new UserDaoImpl();
    }
    //2、说明对象的类型
    public Class<?> getObjectType() {
        return UserDao.class;
    }
    //3、创建的Bean是单例还是非单例
    public boolean isSingleton() {
        return false;
    }

}

配置

 <bean id="ikun" class="com.itheima.factory.UserDaoFactoryBean"/>

六、Bean生命周期

Bean生命周期控制

方法一:提供生命周期控制方法&配置

public class BookDaoImpl implements BookDao{
    public void save(){
        System.out.println("此处是对Dao数据层接口的实现类");
    }
    //表示Bean初始化对应的操作
    public void init(){
        System.out.println("bean初始化");
    }
    //表示Bean销毁对应的操作
    public void destory(){
        System.out.println("bean销毁");
    }

配置(属性:init-method、destroy-method)

<bean id="bookdao1" name="ikun;bkdao2" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>

方法二:实现InitializingBean, DisposableBean接口

public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {
    public void save(){
        System.out.println("此处是对Dao数据层接口的实现类");
    }
    public void destroy() throws Exception {
        System.out.println("service destory");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
}

 七、依赖注入

向一个类中传递数据,咋传?

依赖注入方式:setter注入、构造器注入;                                                                                           依赖注入的数据类型:引用类型、简单类型(基本数据类型与string);

1、setter注入

引用类型

在Bean中定义引用类型属性并提供可访问的Set方法

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    private UserDao userDao;

    public void  setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    //通过以上方法 将spring的Bean通过Set方法传入到此类中
    public void save(){
        bookDao.save();
        userDao.save();
        System.out.println("此处是bookservice的实现类");
    }

配置中使用property标签ref属性注入引用类型对象

<bean id="serviceDao"class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDaoikun"/>
        <property name="userDao" ref="userDaoikun"/>
</bean>

简单类型

bean

public class BookDaoImpl implements BookDao {
    //普通类型注入数据
    private int sumnum;
    private String DBname;
    public void setSumnum(int sumnum) {
        this.sumnum = sumnum;
    }
    public void setDBname(String DBname) {
        this.DBname = DBname;
    }

配置--使用value属性

<bean id="bookDaoikun" class="com.itheima.dao.impl.BookDaoImpl">
           <property name="sumnum" value="100"/>
           <property name="DBname" value="redis"/>
</bean>

2、构造器注入(了解)

和set没啥区别 就是在bean内将set方法换成构造器,将配置的标签换成constructor-arg

引用类型

在Bean中定义引用类型属性并提供可访问的S构造器方法

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    private UserDao userDao;
    //此处是构造器方法 和Set都是个方法嘛

    //注意在constructor内name就是构造方法的形参,ref是不同bean的id
    public BookServiceImpl(BookDao bookDao, UserDao userDao) {
        this.bookDao = bookDao;
        this.userDao = userDao;
    }
    //通过以上方法 将spring的Bean通过构造器方法传入到此类中
    public void save(){
        userDao.save();
        bookDao.save();
        System.out.println("此处是bookservice的实现类");
    }

配置 constructor-arg标签 name ref属性(name就是构造方法的形参,ref是不同bean的id

<bean id="serviceDao"class="com.itheima.service.impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDaoikun"/>
        <constructor-arg name="userDao" ref="userDaoikun"/>
</bean>

普通类型

bean

public class BookDaoImpl implements BookDao {
    private int num;
    private String DBname;

    public BookDaoImpl(int num, String DBname) {
        this.num = num;
        this.DBname = DBname;
    }

    public void save(){
        System.out.println("此处是BookDao的实现类:");
        System.out.println("使用构造器引入普通类型" + num +"," + DBname);
    }

配置

<bean id="bookDaoikun" class="com.itheima.dao.impl.BookDaoImpl">
        <constructor-arg name="num" value="1011"/>
        <constructor-arg name="DBname" value="mysql"/>
</bean>

由于配置内的name要和bean内的构造器方法的形参一致,造成高度耦合,有type、index解耦

 3、使用选择

 八、自动装配

IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程叫做xxxx。

自动装配方式:

按类型:byType(常用)

按名称:byName  (此处的name指的是被依赖注入的bean的id名)(少用-名称耦合度大)

按构造器方法(不常用)

bean内还是直接写引用的对象以及set注入方法

public class UserDaoImpl implements UserDao {
    //在UserDao内引用bookDao对象
    private BookDao bookDao;
    
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
        System.out.println("显示此句子说明采用了set注入二楼");
    }

配置不用写property标签,直接在bean标签内写autowire(注意id写标准,和bean内引用的对象名一样)

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

<bean id="userDaoikun" class="com.itheima.dao.impl.UserDaoImpl" autowire="byName"/>

 九、集合注入(了解-用的极少)

了解一下配置格式就好了

 

 十、案例:数据源对象管理

导入druid(数据库连接池)依赖坐标

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.16</version>
</dependency>

配置数据源对象作为spring管理的bean

<!--    第三方的bean,掌握基本的管理的方法-->
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
</bean>

管理方法:

最基本的配置驱动Driver、URL、username、password。不同的第三方数据源命名有出入,大体一致。

十一、spring加载properties文件

加载properties文件的目的是将一些敏感信息封装,同时也可以信息直接使用变量名代替,方便多次调用。

1、开启context命名空间

在spring的配置文件applicationContext头文件中粘贴修改操作。

 2、使用context空间加载properties文件

接着在applicationContext添加

 <context:property-placeholder location="jdbc.properties"/>
规范格式:
 <context:property-placeholder location="classpath:*.properties"/>
但这种只会在resources文件中读取
要想还能够读取其他文件夹内的jar包
更规范:
<context:property-placeholder location="classpath*:*.properties"/>

3、使用属性占位符${}读取properties文件中的属性

<bean id="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username"/>
        <property name="password" value="${jdbc.password}"/>
</bean>

十二、容器

获取容器的俩种方式:

获取bean:

 容器类层次:

十三、核心容器总结

1、spring核心接口与实现类

2、bean的标签配置

 3、依赖注入的属性配置

第二章:注解开发

一、注解开发定义bean

对于每一个类都需要在spring配置文件中定义bean,有的bean只需要定义一下标签id、class就好了,有的甚至需要写很多属性,set注入就要写很多property属性。那么就会导致配置文件很乱。对于只需要简单获取bean的类,采用注解开发,更简洁。

1、实现类中写上注解@Component("bean名称(和获取的bean定义的名称一致)")

1、
@Component("bookDao")
public class BookDaoImpl implements BookDao {

2、
@Component("bookService")
public class BookServiceImpl implements BookService {

2、spring配置文件通过组件扫描加载bean(会扫描package下辖的所有实现类)

<context:component-scan base-package="com.itheima"/>

衍生注解: Component可以直接被代替(达到见文知作用)

二、纯注解开发

写实现类的注解-写配置类-写获取容器及bean

基本操作:将配置文件用专门写的配置类代替(配置类写上代替的配置文件以及扫描范围);其余的各个实现类中写上注解;使用的spring容器还是ApplicationContext接口,换成实现类AnnotationConfigApplicationContext()传参数为配置类。

1、 配置类:(一般创建在com.xxxx下)(各个标签的作用如上图)

@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}

2、各个实现类的注解如上所讲。

3、获取容器并获取容器的bean(注意容器实现类的参数由配置文件改为配置类!)

public class AppForAnnotation {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }

三、bean作用范围与生命周期

作用范围:添加标签@Scope与单例还是非单例

@Service("bookService")
1、非单例  @Scope("prototype")
2、单例    @Scope("singleton")
public class BookServiceImpl implements BookService {
    public void save(){
        System.out.println("此处是bookservice的实现类");
    }

生命周期:使用@PostConstruct、@PreDestroy

    //bean生命周期添加注解 不用接口
    @PostConstruct
    public void init(){
        System.out.println("此处是构造bean之后的初始化");
    }
    @PreDestroy
    public void destory(){
        System.out.println("此处是销毁bean之前的操作");
    }

四、依赖注入

注解开发目的就是加速开发,对于传统的setter、构造器注入,不做。

自动装配方式

引用类型:

1、基本操作:只需要在被注入的bean上面加入@Autowired;由于自动装配默认采用按类型,所以当有多个相同类型实现类时,就需要再添加@Qualifier(bean名称)来按名称区分。

2、注入方法setter可省略。采用java反射机制,暴力赋值,所以不再需要setter方法注入。

    @Autowired //此句功能就是自动装配 在配置文件层面将dao注入到service
    @Qualifier("bookDao2")
    private BookDao bookDao;

    //public void setBookDao(BookDao bookDao) {
    //    this.bookDao = bookDao;
    //}

 

 

简单类型:

是在引用类型自动装配的基础上,在被注入的bean实现类里面添加要注入的值!

@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao {

    @Value("nishinadendan")
    private String name;
    public void save(){
        System.out.println("此处是bookDao的实现类2" + name);
    }

}

五、加载properties文件

1、properties文件中写入信息

2、配置内中写入标签@PropertySource,参数是properties文件名称

对于多文件,数组形式写入。注解开发此处不支持通配符*

@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties") //配置类中添加properties文件
public class SpringConfig {
}

3、被注入的值 直接使用${}填充

@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao {

    @Value("${jdbc.bb}")
    private String name;
    public void save(){
        System.out.println("此处是bookDao的实现类2" + name);
    }

}

六、第三方bean管理与依赖注入

管理

1、定义一个方法获得想要管理的对象

2、添加@bean,表示当前方法的返回值是一个bean

采用中央式配置类,第三方bean单独写入一个配置类,在spring配置类中@Import。

 

 方式二:扫描式(比较乱--不推荐使用)

每个独立的第三方配置类都要@Configuration;然后在spring核心配置类使用@ComponentScan("com.itheima") 扫描到每一个第三方配置类。

依赖注入

 

 总结:

要会哪些东西?

1、基础:在maven项目基础上,会写pom.xml的依赖;会写spring核心配置文件applicationContext.xml内的bean;

2、总体的话就是两大部分:纯手工配置 & 纯注解开发

基本原理就是:

配置文件 & 配置类

配置文件内配置bean & 配置类写@标签

依赖注入

配置第三方bean

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/865804.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot项目为什么加载不出来页面

路径啥的都没问题。hh&#xff0c;非常简单&#xff0c;因为springboot项目默认访问静态static文件&#xff0c;把那种静态图片放在static文件下就解决了。

订单支付超时未支付关闭订单的解决方案

订单支付超时未支付关闭订单的解决方案 假设有客户下了订单但是迟迟未曾支付&#xff0c;会产生什么样的问题呢&#xff0c;大家联想一下京东淘宝拼多多&#xff0c;想一下大家购物的场景中&#xff0c;人家是怎么做的&#xff0c;然后再看看我们这么这篇文章&#xff01;&…

微信怎么恢复好友?这8个方法值得一试!

【微信之前忘记给别人备注名字&#xff0c;昨天清理好友时不小心误删了该怎么办啊&#xff01;好尴尬&#xff01;】 随着社交网络的快速发展&#xff0c;微信已成为我们生活中必不可少的交流工具。日积月累下来&#xff0c;微信里的联系人也就变得越来越多。但是&#xff0c;…

Map映射学习

一、Map的遍历 创建Map集合 Map<String, Integer> map new HashMap<>();添加元素 map.put("java", 99);map.put("c", 88);map.put("c", 93);map.put("python", 96);map.put("Go", 88); 遍历方法&#xff1a; …

自主学习库简化智能代理创建

观看当今毁灭人类的智能代理玩复杂的视频游戏可能很有趣 - 但创建一个是另一回事。构建有效的智能代理需要设置大量超参数来塑造环境、建立奖励等。来自马萨诸塞大学阿默斯特分校的一组研究人员试图通过他们新的自主学习图书馆项目来简化这一过程。 自治学习库是 PyTorch 的深…

Mysql - 配置Mysql主从复制-keepalived高可用-读写分离集群

目录 高可用&#xff1a; 为什么需要高可用呢&#xff1f; 高可用的主要作用&#xff1a; keepalived是什么&#xff1f;它用在哪里&#xff1f; 什么是VRRP协议&#xff0c;它的作用是什么&#xff1f; 搭建一个基于keepalived的高可用Mysql主从复制读写分离集群 一、项…

【vue3】解决scope.row.id套标签太多无法随着点击按钮而变化

实现要求:再点击每一行的修改按钮时&#xff0c;动态拿取该行的id传给后端作为pk(主键)实现数据库数据的修改&#xff0c;并显示在vue前端&#xff1b; 我遇到的问题&#xff1a;在2处使用 scope 作用域插槽拿取每一行的数据&#xff0c;在3处&#xff0c;删除按钮那一行代码&a…

BGP小综合

实验要求及拓扑 一、思路 1.使用OSPF使R2-R7之间可通。 2.各自宣告AS区域&#xff0c;两个区域两两之间建邻&#xff0c;AS2两个小区域之间建联邦&#xff08;R2与R5、R4与R7&#xff09;。 3.使R3、R6为路由反射器 RR反射器选取各小区域的路由器作为客户端 、非客户端 4.优…

分布式事务模式理论详解

&#x1f680; 分布式事务 &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#x1f3c6;&…

SaaS,PaaS,IaaS之间的主要区别

SaaS&#xff0c;PaaS&#xff0c;IaaS之间的主要区别 不久之前&#xff0c;公司的所有IT系统都是本地部署&#xff0c;而云也只是天空中蓬松的白色物体。现在&#xff0c;几乎所有系统和进程都可以使用云平台。SaaS&#xff0c;PaaS和IaaS只是描述如何在企业中使用云的三种方…

DL_20无线串口模块

今日介绍一块最近入手的无线串口模块&#xff0c;40r左右&#xff0c;精简好用&#xff0c;虽然感觉配置波特率啥的并不智能化&#xff0c;但250米的通信距离还是很顶的&#xff01;它的升级版甚至有1000米的通信距离&#xff08;空旷地带&#xff09; 这篇文章不多讲其余话&am…

(二)结构型模式:1、适配器模式(Adapter Pattern)(C++实现示例)

目录 1、适配器模式&#xff08;Adapter Pattern&#xff09;含义 2、适配器模式应用场景 3、适配器模式的UML图学习 4、C实现适配器模式的示例 1、适配器模式&#xff08;Adapter Pattern&#xff09;含义 将一个接口转换为客户端所期待的接口&#xff0c;从而使两个接口…

Java基础篇--运算符

目录 算术运算符 赋值运算符 比较运算符 逻辑运算符 条件运算符&#xff08;?:&#xff09; instanceof 运算符 Java运算符优先级 在程序中经常出现一些特殊符号&#xff0c;如、-、*、、>等&#xff0c;这些特殊符号称作运算符。运算符用于对数据进行算术运算、赋值…

@RequestHeader使用

RequestHeader 请求头参数的设置 GetMapping("paramTest/requestHeader")public String requestHeaderTest(RequestHeader("name") String name){return name;} 在Postman的Headers中添加请求头参数&#xff0c;不过貌似不能加中文

k8s 滚动更新控制(一)

在传统的应用升级时&#xff0c;通常采用的方式是先停止服务&#xff0c;然后升级部署&#xff0c;最后将新应用启动。这个过程面临一个问题&#xff0c;就是在某段时间内&#xff0c;服务是不可用的&#xff0c;对于用户来说是非常不友好的。而kubernetes滚动更新&#xff0c;…

Java泛型集合简明教程

前言 我们编写一个数组并对数组进行排序&#xff0c;不管是对浮点型数组、整型数组、字符串数组或者是其他任何类型的数组进行排序&#xff0c;我们可以利用方法重载的方式&#xff0c;针对每种类型的数组分别编写一个排序方法&#xff0c;需要为几种类型的数组排序&#xff0…

Java课题笔记~ JSP编程

4.1 JSP基本语法 JSP (全称Java Server Pages) 是由 Sun Microsystems 公司倡导和许多公司参与共同创建的一种使软件开发者可以响应客户端请求&#xff0c;而动态生成 HTML、XML 或其他格式文档的Web网页的技术标准。 JSPHTMLJava JSP的本质是Servlet 访问JSP的时候&#x…

【逗老师的PMP学习笔记】10、项目沟通管理

目录 一、规划沟通管理1、【关键工具】沟通技术2、【关键工具】沟通模型&#xff08;沟通模式&#xff09;3、【关键工具】沟通方法4、【关键工具】文化意识5、【关键输出】沟通管理计划 二、管理沟通1、【关键工具】会议管理 三、监督沟通 一、规划沟通管理 规划沟通管理是基于…

光威神策DDR5 6800超频破10GHz,国产良心价高端内存创造历史

前段时间光威把8000MHz的DDR5内存打到了千元以内&#xff0c;但是因为当时AMD平台还不支持&#xff0c;确实是馋哭了很多AMD玩家&#xff0c;这两天AMD总算发布了新版AM5主板固件&#xff0c;AGESA 1.0.0.7B BIOS&#xff0c;让AMD Ryzen 7000系列CPU和主板能够支持8000MHZ以上…

MySQL 中读写分离可能遇到的问题

前言 MySQL 中读写分离是经常用到了的架构了&#xff0c;通过读写分离实现横向扩展的能力&#xff0c;写入和更新操作在源服务器上进行&#xff0c;从服务器中进行数据的读取操作&#xff0c;通过增大从服务器的个数&#xff0c;能够极大的增强数据库的读取能力。 MySQL 中的…