博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring第一部分
阅读量:5967 次
发布时间:2019-06-19

本文共 3240 字,大约阅读时间需要 10 分钟。

spring的核心两个东西:依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)。

 

一、DI功能是如何实现的

任何一个有实际应用的程序(肯定比helloword复杂)都会有两个或者更多的类组成。传统做法就是每个对象负责管理与自己相互协作的对象的引用,这会导致

高度耦合和难以测试。

public class RescueKnight implements Knight{    private RescueQuest quest;        public RescueKnight(){        this.quest = new RescueQuest();--->高度耦合    }        public void excuteQuest(){        quest.excute();    }}

这样一个类,就有很大的局限性,RescueKnight就只能执行rescue任务,不能执行其他任务,比如杀一只巨龙。

 

 

public class BraveKnight implements Knight{    private Quest quest;        public BraveKnight(Quest quest){        this.quest=quest;    }        public void excuteQuest(){        quest.excute();    }}

 

这个类就厉害了,它通过构造器传入一个Quest类型的任务,这个骑士除了很brave以外,还能执行救援,杀龙等任务。这就是DI实现的最大收益,松耦合。如果一个对象只通过接口来表明依赖,而不是具体的实现,那么就能在毫不知情的情况下用具体实现进行替换。

bean装配

spring有多种bean装配方式,xml文件是比较常见的例子

等同于java代码

@Configurationpublic void KnightConfig{   @Bean   public Knight knight(){     return new BraveKnight(quest());       }   @Bean   public Quest quest(){     return new KillDragonQuest();   }   }

再看上面代码,尽管BraveKnight依赖于Quest,但是并不知道这个Quest传过来的是什么类型的参数,也不知道来自哪里。你只有通过xml配置才知道这些组件这么装配

起来,这样也就能在不改变依赖的情况下修改依赖。实现代码的时候你只要加载xml配置文件,就能获得对象的引用。

 

方法的调用

public class KnightMain {    public static void main(String[] args) {        ClassPathXmlApplicationContext context = new                 ClassPathXmlApplicationContext(".xml");        Knight knight = context.getBean(Knight.class);        knight.excuteQuest();    }}

这个类完全不知道这个骑士执行了什么任务,且不知道是哪个骑士来执行的。

 

二、面向切面编程

面向切面编程是为了促使软件系统实现关注点的一项技术。比如一个系统由多个组件组成,各个组件负责一块特定的功能,但是往往它需要负责功能之外的一些事情。比如打日志功能,这些经常要融入到有核心业务的组件里面去,如果在有核心业务的组件里面去实现打日志功能那么代码会变的很混乱,切如果打日志代码的逻辑需要修改,那么需要到各个组件中修改,即使把打日志写成一个模块,各个组件里面还是会调用这个模块的方法。这样组件不仅仅关注自己的核心功能,还需要知道各个对象需要记日志,还要亲自执行这些功能。

总之使用AOP能使这些组件具有更高的内聚性,更关注自己的核心业务,不需要涉及系统服务所带来的复杂性。

 

比如我们需要一个诗人来对骑士进行歌颂,这是一个记载骑士事迹的服务类。

public class Poet {        public Poet(){            }        public void beforeQuest(){        System.out.println("骑士你太勇敢了!");    }        public void afterQuest(){        System.out.println("骑士你在此次任务中表现的真出色!");    }}

程序中poet类只有两个方法,一个是在骑士执行任务之前调用的,一个是在执行之后。下面让一个knight可以使用poet:

public class BraveKnight implements Knight{        private Quest quest;        private Poet poet;                public BraveKnight(Quest quest,Poet poet){            this.quest=quest;            this.poet=poet;        }                public void excuteQuest(){            poet.beforeQuest();            quest.excute();            poet.afterQuest();        }    }

然后我们只要把poet这个bean注入到knight中就行了,但是为什么诗人的事需要骑士去提醒他做?应该要他自主来完成啊。并且knight的代码变复杂了,而且如果一个knight不需要poet来歌颂事迹呢?

 

--定义切点

首先声明了一个bean在<aop:aspect ref="poet">引用这个bean,<aop:before/>声明了一个前置通知,<aop:after/>声明了一个后置通知,在<aop:pointcut/>

expression里选择要应用通知的位置,语法用的是aspectj的切点表达式语言。

 

execution指示器

1.第一个*表示返回值为任意值,我们不用关心方法的返回值

2.com.qunhe.hengli.springtest表示切点仅匹配springtest这个包,可以写*表示匹配任意的包,就不用关心在哪个包下了

3. .Knight表示匹配Knight这个接口,就不用关心类名了

4. .excuteQuest( . . )指定了方法,并且(. .),表示我们不用关心方法传入的参数类型

 

and表示切点需要匹配所有指示器,当然也可以用or,not

 

within指示器

within(com.qunhe.hengli.springtest.*)表示在springtest包下的任意方法被调用时

转载于:https://www.cnblogs.com/cch-java/p/6384776.html

你可能感兴趣的文章
8 行 Node.js 代码实现代理服务器
查看>>
水印,图片验证码
查看>>
C#编程(七十六)----------使用指针实现基于栈的高性能数组
查看>>
PostgreSql 分页limit
查看>>
在MySQL中创建cm-hive使用的数据库及账号
查看>>
linux下限制ip访问
查看>>
linux添加环境变量
查看>>
Dumpsys Input Diagnostics
查看>>
ASP.NET MVC 入门8、ModelState与数据验证
查看>>
Understanding the Router
查看>>
组件居中显示 安卓
查看>>
delete
查看>>
sql server生成不重复的时间字符串
查看>>
DataBase 之 数据库设计六大范式
查看>>
比特币钱包安全
查看>>
Lucene就是这么简单
查看>>
2015年第6届蓝桥杯Java B组省赛试题解析
查看>>
一个有味道的函数
查看>>
zookeeper在linux环境安装
查看>>
Python_异常和模块
查看>>