spring实战读书笔记spring之旅(代码片段)

xiueer xiueer     2023-02-06     115

关键词:

Spring可以做很多事情,但是这个事情底层都依赖于2个核心特征:依赖注入(DI)和面向切面编程(AOP)

概念:POJO:简单java对象,Plain Old Java Object,在Spring中基本可以等同于javabean

为了简化Java开发的复杂性,Spring采用了4个关键策略

(1)基于POJO的轻量级和最小侵入性编程

(2)基于DI和面向接口实现松耦合

(3)基于切面和惯例进行声明式编程

(4)通过切面和模板减少样板式代码

1、Spring减少侵入性代码,保持POJO的简洁

在早期的框架如Struts等,会要求应用继承他们的类或实现他们的接口,这就导致了应用与框架绑定。而在Spring中会尽量避免这种框架代码与应用代码耦合的情况出现,获取会有在代码中加入Spring注解的情况,但是它本身还是一个POJO。为了能够实现这种解绑,其方式之一就是使用DI来装配bean

2、DI依赖注入

实际开发中,不可能只由一个类负责全部的事情,一定存在多个类之间的调用。一般情况下类A调用B的方法时,会在A中new一个B的对象,然后调用之。这样必然导致了高耦合。

所以我们可以考虑以DI方式处理,对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定,对象本身无需自行创建或管理他们的依赖关系。更重要的是,传入的类型是一个接口,而不是一个具体的类,任何实现了Account的类都可以被注入进来。Bank并没有与任何特定的Account实现类发生耦合。

public interface Account 
    public void addMoney();
    public void subtractMoney();


public class Bank 
    private Account account; // account是接口

    public Bank(Account account)
        this.account = account;
    

    public void save()
        account.addMoney();
    

现在ObjectA可以接受任何一种实现了InterfaceB的类的注入。为了能够将具体的类注入到ObjectA中,我们需要进行一些配置。即装配:创建应用组件之间协作的行为通常成为装配

public class Account1 implements Account 
    @Override
    public void addMoney() 
        System.out.println("+100");
    

    @Override
    public void subtractMoney() 
        System.out.println("-100");
    
<?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 id="bank" class="test.Bank">
        <constructor-arg ref="account1"/>
    </bean>

    <bean id="account1" class="test.Account1">
    </bean>
</beans>

在上面的配置文件中,ObjectA和ObjectB都被声明为Spring中bean,ObjectA bean在构造时传入了ObjectB的引用,并将其作为构造器参数。除了上面的xml方式的配置,还可以使用基于Java的配置。不管使用哪种方式,其作用是相同的。ObjectA依赖于InterfaceB,但是却并不知道传递给他的是什么类型的InterfaceB,也不知道来自哪里。这样就可以在不改变依赖的类(接口)的情况下,修改依赖关系。

Spring使用应用上下文(ApplicationContext)装载bean的定义并把他们组合在一起,Spring提供了多种应用上下文的实现,如ClassPathXMLApplicationContext可以用来加载xml配置文件。还有其他多种应用上下文,根据具体情况使用。

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMain 
    public static void main(String[] args) 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/META_INF/spring.xml")
    

3、AOP切面

DI能够让互相写作的软件组件保持松耦合,而面向切面编程(AOP)允许你把遍布应用各处的功能分离出来形成可以重用的组件。

最常见的AOP应用场景就是日志打印和事务控制。每一个组件的开发都可能设计到日志和事务,但是这并不是组件自身的核心业务,他们分散在代码的各处,显然增加了维护的成本。AOP能够是这些服务模块化,并以声明的方式将他们应用到各组件中去。使得各个组件具有更高的内聚性并更关注与自身的业务,不需要了解涉及系统服务所带来的复杂性。AOP能够确保POJO的简洁性。

现在想要在Bank的save方法执行前后加上日志,用于记录save的动作。只需要先定义一个log类,然后做一些AOP相关的配置即可。原Bank代码无需做任何的改动。 

public class Log 
    public void logBefore()
        System.out.println("you add 100");
    
    public void logAfter()
        System.out.println("you subtrace 100");
    
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <bean id="bank" class="test.Bank">
        <constructor-arg ref="account1"/>
    </bean>

    <bean id="account1" class="test.Account1">
    </bean>

    <bean id="logger" class="test.Log">
    </bean>

    <aop:config>
        <aop:aspect ref="logger">
            <aop:pointcut id="log" expression="execution(* *.save(..))"/>
            <aop:before pointcut-ref="log" method="logBefore"/>
            <aop:after pointcut-ref="log" method="logAfter"/>
        </aop:aspect>
    </aop:config>

</beans>

首先,把Log声明为一个bean,并在<aop:aspect>中引用这个bean。aop:pointcut是切入点,并配置表达式expression属性来选择所应用的通知。aop:before和aop:after是前置通知和后置通知,分别在save方法的前后被调用。

 

面试题,简单介绍一下你对spring的理解

什么是依赖注入

什么是AOP

DI和IoC的关系

spring实战读书笔记spring装配bean(代码片段)

...过Xml装配Bean借助构造器注入初始化bean设置属性混合配置Spring容器负责创建应用程序中的bean并通过DI来装配(wiring)他们。Spring有三种装配方式,三种方式可以搭配使用 (1)隐式的bean发现 查看详情

spring实战读书笔记spring装配bean(代码片段)

...过Xml装配Bean借助构造器注入初始化bean设置属性混合配置Spring容器负责创建应用程序中的bean并通过DI来装配(wiring)他们。Spring有三种装配方式,三种方式可以搭配使用 (1)隐式的bean发现机制和自动装配ÿ... 查看详情

springinaction读书笔记--第1章spring之旅

1.简化Java开发    Spring是一个开源框架,它的根本使命在于简化java开发。为了降低java开发的复杂性,Spring采取了以下4种关键策略:       1.基于POJO的轻量级和最小侵入性编程;  &nb... 查看详情

前方高能预警!阿里大佬出品“spring实战学习笔记”震撼来袭!(代码片段)

Spring框架已经成为Java开发人员的必备知识,而且Spring3引入了强大的新特性,例如SpEL、Spring表达式语言、loC容器的新注解以及用户急需的对REST的支持。无论你是刚刚接触Spring还是被Spring3.0的新特性所吸引,这份笔记... 查看详情

前方高能预警!阿里大佬出品“spring实战学习笔记”震撼来袭!(代码片段)

Spring框架已经成为Java开发人员的必备知识,而且Spring3引入了强大的新特性,例如SpEL、Spring表达式语言、loC容器的新注解以及用户急需的对REST的支持。无论你是刚刚接触Spring还是被Spring3.0的新特性所吸引,这份笔记... 查看详情

spring学习笔记——spring之旅

1、简化Java开发  Spring——Spring是一个开源框架,它是为了解决企业级Java开发的复杂性而创造的。  为降低Java开发的复杂性,Spring采用了以下四种关键策略:基于POJO的轻量级和最小侵入性编程;  通过依赖注入和面向接... 查看详情

《effectiveobjective-c2.0》读书/实战笔记三(代码片段)

《EffectiveObjective-C2.0》读书/实战笔记三《EffectiveObjective-C2.0》读书/实战笔记一《EffectiveObjective-C2.0》读书/实战笔记二第6章:块与大中枢派发第37条:理解“块”这一概念块是C、C++、Objective-C中的语法闭包块可接受参... 查看详情

《spring实战(第三版)》之旅

...糊。  反正经过这五大框架的学习,感觉最重要的还是Spring框架,于是乎,开学时期偶得一书《Spring实战》,在网上口碑还是蛮高的,于是继续深入学习(复习)下Spring这个框架。  到目前为止已经读到了第8章使用SpringWebFl... 查看详情

java并发编程实战读书笔记executorcompletionservice(代码片段)

当我们向Executor提交一组任务,并且希望任务在完成后获得结果,此时可以考虑使用ExecutorCompletionService。ExecutorCompletionService实现了CompletionService接口。ExecutorCompletionService将Executor和BlockingQueue功能融合在一起,使用它... 查看详情

java并发编程实战读书笔记executorcompletionservice(代码片段)

当我们向Executor提交一组任务,并且希望任务在完成后获得结果,此时可以考虑使用ExecutorCompletionService。ExecutorCompletionService实现了CompletionService接口。ExecutorCompletionService将Executor和BlockingQueue功能融合在一起,使用它... 查看详情

《java8实战》读书笔记12:函数式编程(代码片段)

《Java8实战》读书笔记12:函数式编程第13章函数式的思考13.1实现和维护系统13.1.1共享的可变数据13.1.2声明式编程13.2什么是函数式编程13.2.1函数式Java编程13.2.2引用透明性13.2.3面向对象的编程和函数式编程的对比13.2.4函数式编... 查看详情

java并发编程实战读书笔记之futuretask(代码片段)

在《AndroidAsyncTask源代码浅析》一文中介绍了AndroidAsyncTask的原理,里面也初步介绍了FutureTask的使用方法。在创建Future的时候,根据其构造器来看需要传一个Callable对象,其构造器如下。publicFutureTask(Callable<V>callable)this.callable=c... 查看详情

java并发编程实战读书笔记之futuretask(代码片段)

在《AndroidAsyncTask源代码浅析》一文中介绍了AndroidAsyncTask的原理,里面也初步介绍了FutureTask的使用方法。在创建Future的时候,根据其构造器来看需要传一个Callable对象,其构造器如下。publicFutureTask(Callable<V>callable)this.callable=c... 查看详情

springinaction读书笔记——容器和依赖注入(代码片段)

容器java程序员都知道IOC和AOP是Spring的两大核心概念。IOC是控制反转,也就是通过注入的方式把原本由类自己完成的内部依赖对象实例化这个行为转交给Spring的容器去完成。IOC之后的一个很大的好处就是:代码里消除了无... 查看详情

读书笔记博客实战之搜索引擎索引和流量涨跌策略分析[图](代码片段)

...就来分析一下这几天百度在流量涨跌方面有什么变化吧。实战分析:读书笔记博客,主要用于教育类话题的写作和学习,采用老域名制作的新站,通过该网页的排名变化情况来分析(名人传读书笔记http://www.simayi.net/dushubiji/992. 查看详情

java并发编程实战读书笔记(代码片段)

1、无状态对象一定是线程安全的。因为无状态的对象不包含任何变量或者其他类的引用。2、在某线程修改某变量的时候,需要通过某种方式,比如加锁,来防止其他线程使用该变量。3、在java.util.concurrent包含了一些... 查看详情

java并发编程实战读书笔记(代码片段)

1、无状态对象一定是线程安全的。因为无状态的对象不包含任何变量或者其他类的引用。2、在某线程修改某变量的时候,需要通过某种方式,比如加锁,来防止其他线程使用该变量。3、在java.util.concurrent包含了一些... 查看详情

《java8实战》读书笔记10:组合式异步编程completablefuture(代码片段)

《Java8实战》读书笔记10:组合式异步编程CompletableFuture第11章CompletableFuture:组合式异步编程11.1Future接口(只是个引子)11.1.1Future接口的局限性11.1.2使用CompletableFuture构建异步应用11.2实现异步API11.2.0同步版本Shop类&... 查看详情