Spring

Spring

spring是什么

Spring是一个主流的JavaWeb开发框架,该框架是一个轻量级的应用框架,具有很高的凝聚力和吸引力。Spring框架因为其强大的功能和牛逼的性能越来越受开发人员的喜欢。那就跟光棍五十年遇到女人一样的饥渴啊。

Spring是分层的 Java SE/EE full-stack 轻量级开源框架,以IOC(Inverse of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为内核,使用基本的JavaBean完成以前只可能由EJB完成的工作,取代了EJB臃肿和低效的开发模式。

在实际开发中,通常服务器端采用分层架构——表现层(web)、业务逻辑层(service)、持久层(dao)。

Spring对每一层都提供了技术支持,在表现层提供了与Struts2框架的整合,在业务逻辑层可以管理事务和记录日志,在持久层可以整合Hibernate和JdbcTemplate等技术。

从设计上看,Spring框架给予了Java程序员更高的自由度(像苏菲一样,想咋跳就咋跳),所以受到了业界的一致好评。

Spring具有简单,可测试和松耦合等特点,不仅可以用于服务器端的开发,也可以应用于任何Java应用的开发中。

Spring特点是什么

支持AOP,方便进行面向切面的编程

方便解耦:简化开发,通过Spring提供的IoC容器(控制反转),利用依赖关系注入的方式,实现对象之间的解耦。

支持声明式事务处理,只需要通过配置就可以完成对事物的管理,而无须手动编程

方便程序的测试:Spring提供了对Junit4的支持,可以通过注解方便的测试Spring程序。

方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。

降低Java EE API的使用难度:Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。

非侵入式设计 Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。

Spring优势什么

1)方便解耦,简化开发

Spring就像一个大工厂,可以将所有对象的创建和依赖关系的维护交给Spring管理(你可以想象一下养老院)

2)方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts2、Hibernate、MyBatis)的直接支持。

3)降低Java EE API 的使用难度

Spring对Java EE 开发中非常难用的一些API(JDBC、JavaMail、远程调用等)都提供了封装,使这些API应用的难度大大降低。

4)方便程序的测试

Spring支持JUnit4,可以直接通过注解方便的测试Spring程序

5)AOP编程的支持

Spring提供面向切面编程,可以方便的实现对程序进行权限拦截和运行监控等功能。

6)声明事务的支持

只需要通过配置就可以完成对事务的管理,而不用我们去手动编程。

耦合是什么意思

耦合是指两个实体相互依赖于对方的一个量度。

分为以下几种:

  • 非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的
  • 数据耦合:一个模块访问另一个模块时,彼此之间是通过简单数据参数 (不是控制参数、公共数据结构或外部变量) 来交换输入、输出信息的。
  • 标记耦合 :一组模块通过参数表传递记录信息,就是标记耦合。这个记录是某一数据结构的子结构,而不是简单变量。
  • 控制耦合:如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合。
  • 外部耦合:一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
  • 公共耦合:若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
  • 内容耦合:如果发生下列情形,两个模块之间就发生了内容耦合
    • (1) 一个模块直接访问另一个模块的内部数据;
    • (2) 一个模块不通过正常入口转到另一模块内部;
    • (3) 两个模块有一部分程序代码重迭(只可能出现在汇编语言中);
    • (4) 一个模块有多个入口。

spring核心是什么

1.控制反转(IoC,Inversion of Control)

传统的JAVA开发模式中,当需要一个对象时,我们使用new或者通过getInstance等直接或者间接调用构造方法创建一个对象,而在Spring开发模式中,Spring容器使用工厂模式为我们创建了所需要的对象,不需要我们自己去创建了,直接调用Spring提供的对象就可以了,这就是控制反转

2.面向切面编程(AOP)

在面向对象编程(OOP)中,我们将事务纵向抽成一个个的对象,而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制,事务管理,日志记录等公用操作处理的过程,就是面向切面编程的思想。

IOC 什么含义

**Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。**在Java开发中,**Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。**如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

DI是什么?

I—Dependency Injection,即“依赖注入”组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。**依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。**通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  • 谁依赖于谁:当然是应用程序依赖于IoC容器
  • 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源
  • 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象
  • 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

DI和IOC的区别

IOC:控制反转,把对象创建交给spring进行配置

DI:依赖注入,向类里面的属性中设置值

关系:依赖注入不能单独存在,需要在ioc的基础之上完成操作

属性注入的方式

Users.java

package kevin.demo.bean;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class Users {
    private Integer userid;
    private  String username;
    private  String password;
    public Users(String name,String pwd,Integer uid){
        System.out.println("users带参构造方法。。。。");
        this.userid = uid;
        this.password=pwd;
        this.username=name;
    }
    public  Users(){
        System.out.println("users无参构造方法。。。。");
    }
    public void say(){
        System.out.println("hello,spring");
    }
}

set方式注入:

beans.xml

<!--set注入:set方法-->
    <bean id="users" class="kevin.demo.bean.Users" >
        <property name="userid" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
    </bean>

    

UsersTest.java

    @Test
    public  void  test02(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Users users =  context.getBean("users",Users.class);
        System.out.println(users.getUserid()+"\t"+users.getUsername()+"\t"+users.getPassword());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MpHPHFWP-1631611739840)(C:\Users\10690\AppData\Roaming\Typora\typora-user-images\image-20210913162740367.png)]

构造方式注入:

beans.xml

 <!--构造子注入:构造函数-->
    <bean id="users2" class="kevin.demo.bean.Users">
        <constructor-arg name="name" value="root"></constructor-arg>
        <constructor-arg name="pwd" value="147258"></constructor-arg>
        <constructor-arg name="uid" value="2"></constructor-arg>
    </bean>

UsersTest.java

    @Test
    public void test03(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Users users =  context.getBean("users2",Users.class);
        System.out.println(users.getUserid()+"\t"+users.getUsername()+"\t"+users.getPassword());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-or3NfT3C-1631611739842)(C:\Users\10690\AppData\Roaming\Typora\typora-user-images\image-20210913162526488.png)]

Spring管理bean的作用域

  1. singleton(单实例)

Spring Bean 中所说的作用域,在配置文件中即是“scope”

<bean id="person" class="com.spring.Person" scope="singleton"></bean>

测试

@Test
	public void test(){
		// ApplicationContext是接口
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
        Person person1 =(Person)ctx.getBean("person");
        Person person2 =(Person)ctx.getBean("person");
        System.out.println(person1==person2);
	}

结果是:true

说明了默认情况下bean交给Spring容器管理之后,这个bean就是一个单实例(单例模式)的,即每次调用getBean()方法,获取到的都是同一个bean实例。

  1. prototype

修改scope的值

<bean id="person" class="com.spring.Person" scope="prototype"></bean>
@Test
	public void test(){
		// ApplicationContext是接口
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
        Person person1 =(Person)ctx.getBean("person");
        Person person2 =(Person)ctx.getBean("person");
        System.out.println(person1==person2);
	}

打印结果为:false

说明它们不是同一个实例,每getBean()方法都会产生新的实例

对于有状态的Bean应该使用prototype,对于无状态的Bean则使用singleton

  1. request

Request作用域针对的是每次的Http请求,Spring容器会根据相关的Bean的
定义来创建一个全新的Bean实例。而且该Bean只在当前request内是有效的。

  1. session

针对http session起作用,Spring容器会根据该Bean的定义来创建一个全新的Bean的实例。而且该Bean只在当前http session内是有效的。

  1. global session

Spring管理bean的生命周期

【1】实例化 Bean:对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 bean时,或初始化 bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean进行实例化。对于 ApplicationContext容器,当容器启动结束后,便实例化所有的单实例 bean。容器通过获取 BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。实例化对象被包装在 BeanWrapper 对象中,BeanWrapper 提供了设置对象属性的接口,从而避免了使用反射机制设置属性。通过工厂方法或者执行构造器解析执行即可:创建的对象是个空对象。

【2】设置对象属性(依赖注入):实例化后的对象被封装在 BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。紧接着获取所有的属性信息通过 populateBean(beanName,mbd,bw,pvs),Spring 根据 BeanDefinition 中的信息进行依赖注入。并且通过 BeanWrapper提供的设置属性的接口完成依赖注入。赋值之前获取所有的 InstantiationAwareBeanPostProcessor 后置处理器的 postProcessAfterInstantiation() 第二次获取InstantiationAwareBeanPostProcessor 后置处理器;执行 postProcessPropertyValues()最后为应用 Bean属性赋值:为属性利用 setter 方法进行赋值 applyPropertyValues(beanName,mbd,bw,pvs)。

【3】bean 初始化:initializeBean(beanName,bean,mbd)。

  1. 执行xxxAware 接口的方法,调用实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的方法。

  2. 执行后置处理器之前的方法:applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)所有后置处理器的 BeanPostProcessor.postProcessBeforeInitialization()

  3. 执行初始化方法: InitializingBean 与 init-methodinvoke 当 BeanPostProcessor的前置处理完成后就会进入本阶段。先判断是否实现了 InitializingBean接口的实现;执行接口规定的初始化。其次自定义初始化方法。

    InitializingBean 接口只有一个函数:afterPropertiesSet()这一阶段也可以在 bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前 bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。若要使用它,我们需要让 bean实现该接口,并把要增加的逻辑写在该函数中。然后 Spring会在前置处理完成后检测当前 bean是否实现了该接口,并执行 afterPropertiesSet函数。当然,Spring 为了降低对客户代码的侵入性,给 bean的配置提供了 init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring 便会在初始化阶段执行我们设置的函数。init-method 本质上仍然使用了InitializingBean接口。

  4. applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);执行初始化之后的后置处理器的方法。BeanPostProcessor.postProcessAfterInitialization(result, beanName);

【4】Bean的销毁:DisposableBean 和 destroy-method:和 init-method 一样,通过给 destroy-method 指定函数,就可以在bean 销毁前执行指定的逻辑。

Bean 的管理就是通过 IOC 容器中的 BeanDefinition 信息进行管理的。

Spring中bean的两种方式

Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)

1、普通 bean:在配置文件中定义 bean 类型就是返回类型

lt, beanName);

【4】Bean的销毁:DisposableBean 和 destroy-method:和 init-method 一样,通过给 destroy-method 指定函数,就可以在bean 销毁前执行指定的逻辑。

Bean 的管理就是通过 IOC 容器中的 BeanDefinition 信息进行管理的。

Spring中bean的两种方式

Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)

1、普通 bean:在配置文件中定义 bean 类型就是返回类型

2、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值