第1章—Spring之旅—简化Spring的java开发

简化Spring的java开发

1.1简介

区别于EJB的特性 简化javaBean,为了降低java开发的复杂性,Spring采取了以下4种关键策略:

  • 基于POJO的轻量级和最小入侵性编程
  • 通过依赖注入和面向接口实现松耦合
  • 基于切面和惯例进行声明式编程
  • 通过切面和模板减少样板式代码

1.2依赖注入(DI)

​ 依赖注入到底是什么呢?任何一个有实际意义的应用都会由两个或者多个类组成,这些类进行相互协作来完成特定的业务逻辑.按照传统的做法,没个对象负责管理与自己相互协作的对象(即它所依赖的对象)的引用,这将会导致高度耦合和难以测试的代码.

例子:

骑士去探险

/**
 * 骑士
 */
public interface Knight {
    public void embarkOnQuest();
}
/**
 *
 * 探险类型
 */

public interface Quest {
    public  void embark();
}
/**
 * 勇敢的骑士
 */

public class BraveKnight implements Knight {

    private Quest quest;

    //quest被注入进来(构造注入)
    public BraveKnight(Quest quest) {
        this.quest = quest;
    }

    public void embarkOnQuest() {
        quest.embark();
    }
}

这个例子中的Quest是通过构造参数传递进来的,这里的重点是BraveKnight没有与任何特定的Quest实现发生耦合.对于它来说,被要求挑战的探险任务只要实现了Quest接口,那么具体是哪种类型的探险就无关紧要了.这就是DI所带来的最大收益 - - 松耦合.

对依赖进行替换的时候只需要给Quest的接口一个实现类即可

/**
 * 任务的实现类
 */
public class QuestImpl implements Quest{
    //从事 开始方法
    public  void embark() {
        System.out.println("开始探险");
    }
}
/**
     * 进行依赖的测试
     */
    @Test
    public void KinghtShouldEmbarkOnQuest() {
        //向上转型
        Quest questimpl = (Quest) new QuestImpl();
        //注入Quest的实现类QuestImpl
        BraveKnight knight = new BraveKnight(questimpl);
        //执行方法
        knight.embarkOnQuest();
    }

1.3通过Spring的Xml进行配置实现

application.xml

<?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">

<!--注入BraveKnight-->
<bean id="braveKnight" class="BraveKnight">
    <constructor-arg ref="quest"/>
</bean>
    <!--注入QuestImpl-->
    <bean id="quest" class="QuestImpl"></bean>
</beans>

进行Spring的测试

public static void main(String[] args) {
        //加载配置文件 加载Spring的上下文
        ApplicationContext app = new ClassPathXmlApplicationContext("classpath:application.xml");
        //获取bean
        BraveKnight bean = app.getBean(BraveKnight.class);
        //调用方法
        bean.embarkOnQuest();
    }

1.4应用切面编程(AOP)

​ 上面已经介绍了DI能够让互相协作的软件组织 保持松耦合,而面向切面编程(AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件.

​ 常见的AOP抽离出来的组件有:日志模块;事务模块;安全模块等.

​ AOP能够让服务模块化,并以声明的方式将他们应用到他们需要影响的组件中去.这样做的好处是可以让这些组件具有更高的内聚性并且更加关注自身的核心业务,完全不需要了解设计系统服务所带来的复杂性,总之,AOP能够确保POJO的简单性. 我们可以把切面想象为覆盖在很多组件之上的一个外壳,如下图所示:

image

例子:还是以刚才的骑士为例,我们熟知吟游诗人这个服务类会来记载骑士的所有事迹.

主要的类如下:

//吟游诗人作为切面
public class Minstrel {

    public void  singBeforeQuest(){
        //探险之前
        System.out.println("Before: Fa la la ,the Knight is so breave!");
    }

    public void  singAfterQuest(){
        //探险之后
        System.out.println("After: Tee hee hee ,the breave Knight!");
    }
}

AOP的XMl配置的实例如下:

<?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.xsd">

    <!--注入BraveKnight-->
    <bean id="braveKnight" class="BraveKnight">
    <constructor-arg ref="quest"/>
    </bean>

    <!--注入QuestImpl-->
    <bean id="quest" class="QuestImpl"/>

    <!--AOP实例-->
    <!--注入Minstrel-->
    <bean id="minstrel" class="com.aop.Minstrel"/>
    <aop:config>
        <!--声明切面-->
        <aop:aspect ref="minstrel">
            <!--定义切点 这里定义的是骑士的方法-->
            <aop:pointcut id="embark" expression="execution(* QuestImpl.embark(..))"/>
            <!--声明前置通知-->
            <aop:before pointcut-ref="embark" method="singBeforeQuest"/>
            <!--声明后置通知-->
            <aop:after pointcut-ref="embark" method="singAfterQuest"/>
        </aop:aspect>
    </aop:config>
</beans>

AOP的主要配置涉及到切面和切点,我们先定义横切面的类的Bean并进行注入,然后我们需要相关的类的方法作为切点,AOP的主要用法有:前置通知;后置通知;环绕通知,用于在核心代码前面后面加入相关的切面的代码的实现.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA高级架构

女程序员的梦,众网友的神回复

女程序员发的一条微博: “昨晚梦见男朋友和别的女人在逛街,梦里我的第一反应就是查源代码,结果调试半天查不出来为什么显示的那个女人不是我,最后含泪把那个女人注释掉...

3455
来自专栏小樱的经验随笔

自己手动复现一个熊猫烧香病毒

最近逛了一下 bilibili ,偶然的一次机会,我在 bilibili 上看到了某个 up 主分享了一个他自己仿照熊猫病毒的原型制作的一个病毒的演示视频,虽然...

6352
来自专栏XAI

企业支付宝账号开发接口教程--JAVA-UTF-8(实际操作------SpringMVC+JSP)

关于即时到账的开发。审核通过。简单测试如下。 希望看的可以收藏或者赞一下哦。 1:拥有自己的支付宝企业账号。去产品商店选择适合自己的方案。并签约合同。 ? 2:...

1.4K9
来自专栏YouMeek

我的 Firefox 扩展 和 主题(不间断更新)

初衷 整理自己的习惯,也希望你有好的扩展可以留言给我推荐,能提高效率的事情我非常需要! 不对下面扩展进行再唠叨,具体点击到扩展主页可以看到对应的说明。 扩展 整...

4839
来自专栏我的小碗汤

这个坑你能填吗?

今天利用java发邮件,本地windows上测试时发送ok的,部署到服务器上却报异常,让我们走进异常,探索到底坑在哪里,并填之。

1002
来自专栏郭霖

巧用Android网络通信技术,在网络上直接传输对象

要做一个优秀的Android应用,使用到网络通信技术是必不可少的,很难想象一款没有网络交互的软件最终能发展得多成功。那么我们来看一下,一般Android应用程序...

2256
来自专栏程序员笔记

celery 定时任务实现

3954
来自专栏老码农专栏

原 荐 一场版本升级引发的性能血案 - 之数

2313
来自专栏coder修行路

Go基础之--位操作中你所不知道的用法

之前一直忽略的就是所有语言中关于位操作,觉得用处并不多,可能用到也非常简单的用法,但是其实一直忽略的是它们的用处还是非常大的,下面先回顾一下位操作符的基础 位操...

2126
来自专栏JackieZheng

学习Spring——两个你熟悉的不能再熟悉的场景使用

  最近公众号受邀获取了留言和赠送模板的权限,小开心(欢迎去公众号JackieZheng围观)。   我们大致的了解了Spring这个框架对于依赖注入的使用和诠...

2075

扫码关注云+社区

领取腾讯云代金券