2019-04-20 22:05:58 +0000   |     java spring gradle   |   Viewed times   |    

【春】晓

几日不晨跑,草地变绿了。 连绵阴雨后,又是西瓜好。

摘要

  1. Spring能用依赖注入自动装配实例。
  2. Spring的AOP(面向切面)组件能把很多事务性功能分离出来
  3. Spring的模板很简化很多像JDBC这样的僵硬代码。

1.1.1 HelloWorld例子

代码地址 -> https://github.com/helloShen/spring-in-action-4th-edition-demo/tree/master/ch01/src/main/java/com/ciaoshen/sia4/ch01/helloworld_111

封装在helloworld_111包下,结构如下,

└── com
    └── ciaoshen
        └── sia4
            └── ch01
                └── helloworld_111
                    ├── HelloWorldBean.class
                    ├── HelloWorldMain.class
                    └── config
                        └── HelloWorldConfig.class

最简单的Spring应用。初始化管理bean的context容器,然后通过context容器调用bean。

1.1.2 依赖注入,Knight-Quest例子

代码地址 -> https://github.com/helloShen/spring-in-action-4th-edition-demo/tree/master/ch01/src/main/java/com/ciaoshen/sia4/ch01/knights_112

封装在knights_112包下,结构如下,

└── com
    └── ciaoshen
        └── sia4
            └── ch01
                └── knights_112
                    ├── BraveKnight.class
                    ├── Knight.class
                    ├── KnightMain.class
                    ├── Quest.class
                    ├── SlayDragonQuest.class
                    └── config
                        └── KnightConfig.class

一个最简单的依赖注入例子,目标是将骑士Knight类和他将要执行的任务Quest类解耦。具体方法是将Quest做为Knight的一个字段,并通过Knight的构造函数指定(注入)。

其中,KnightQuest都是接口。具体实现类分别是BraveKnightSlayDragonQuestKnight的构造函数接受一个Quest型参数,来决定这个骑士专门执行什么任务。

具体执行类KnightMain只负责让一个Knight型的bean执行他的专属Quest。具体是哪个骑士,执行的是哪个任务,执行类完全不需要关心。全部由KnightConfig负责。它具体将BraveKnight注册成唯一的一个Knight型bean,并将另一个唯一的Quest型beanSlayDragonQuest注入其中。

至此无论是类的定义层面还是最后的执行层面,完全做到面向接口编程。Knight只需要知道他能执行Quest。最后是由spring(KnightConfig类)决定具体招募哪个骑士,并给他指派哪个任务。

打包可执行JAR的时候遇到坑

详见 -> http://www.ciaoshen.com/java/2019/04/20/about-executable-jar.html

knights.xml配置失败

报错显示解析src/main/resources/spring/knights.xml的时候,http://www.springframework.org/schema/beans/spring-beans-4.0.xsd中找不到beans元素。

1.1.3 面向切面编程(AOP),Minstrel例子

代码地址 -> https://github.com/helloShen/spring-in-action-4th-edition-demo/tree/master/ch01/src/main/java/com/ciaoshen/sia4/ch01/minstrel_113

封装在minstrel_113包下,

└── com
    └── ciaoshen
        └── sia4
            └── ch01
                └── minstrel_113
                    ├── BraveKnight.class
                    ├── Knight.class
                    ├── Minstrel.class
                    ├── MinstrelMain.class
                    ├── Quest.class
                    ├── SlayDragonQuest.class
                    └── config
                        └── MinstrelConfig.class

KnightQuest的框架延续1.1.2的例子。目标是加入Minstrel切面类。负责在每个骑士执行embarkOnQuest()函数之前调用MinstrelsingBeforeQuest()函数,并在任务完成之后调用singAfterQuest()函数。

书上用的是XML配置法。之前XML配置法有问题,而且现在不常用了,所以该用AspectJ配置。先在Minstrel类里用AspectJ的@Aspect@Before@After注解定义切面。然后在MinstrelConfig配置类里,把Minstrel定义成除了KnightQuest型之外的第三个bean。

至此,Minstrel只是spring中的一个普通bean。虽然被定义成了切面,但spring不会将他视为切面。它关于切面的所有注解不会被解析,也不会转换成切面代理。必须最后在MinstrelConfig类上打上spring-context包里的@ComponentScan@EnableAspectJAutoProxy注解,告诉spring自动扫描切面类,并自动包装成切面代理。这时Minstrel的前置和后置通知才能被织入到Knight-Quest的事务中。

其他

第一章其他内容都是泛泛而谈。之后章节会具体介绍。