JavaEE开发之Spring中的依赖注入与AOP
上篇博客我们系统的聊了《JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建》,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的Runtime来实现了ObjC中的依赖注入,相关博客请参考《类比Spring框架来实现OC中的依赖注入》。当然之前的博客也是使用了ObjC的Runtime的东西来实现了ObjC中的“面向切面”编程的实现方式,相关博客请移步于《ObjC中的AOP--面向切面编程》。本篇博客我们就来看一下Spring框架中的依赖注入以及AOP编程的几种方式,当然其实现方式是使用了Java的“反射机制”,也就类似于ObjC中的Runtime了。
今天博客中所使用的Spring版本是4.3.6.RELEASE,是目前比较新的Spring版本了。而Java的版本使用的是Java8了。上篇博客我们主要聊了相关环境的创建与配置,本篇博客将不会对环境配置这些东西进行详细的叙述。本篇博客主要聊了Spring框架中的依赖注入的实现方式,主要是通过注解以及Java配置来实现的,当然还会聊些AOP的东西。
一、快速创建Mava管理的Spring工程
因为本篇博客是讨论关于Spring的东西,所以我们就不创建WebApp的工程了。我们使用Spring来快速的创建一个Maven管理的工程。如下所示找到File->New->Maven Project选项来创建一个新的Maven Project,具体如下所示:
下方我们选择创建一个简单的Maven工程,跳过模板的选择。上篇博客我们在创建Maven工程时,是没有选择下方这个选项的,然后我们选择了一个WebApp的模板。而本篇博客,我们不需要WebApp的模板,只需要一个简单的Maven工程即可。
接着输入组织名和工程名,如下所示。点击Finish即可完成Maven简单工程的创建。
下面就是我们创建好的Maven 工程的目录结构,我们的工程代码要放在src/main/java中,稍后会使用到。
创建好上述工程后,我们要在pom.xml中引入我们的Spring依赖包。下方xml就是pom.xml中的内容。我们先引入了spring-context包,如下所示:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zeluli</groupId>
<artifactId>SpringDemoWithMaven</artifactId>
<version>0.0.1-SNAPSHOT</version> <properties>
<java.version>1.8</java.version>
<spring.version>4.3.6.RELEASE</spring.version>
</properties> <dependencies>
<!-- Spring 核心包的引入 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-complier-plugin</artifactId>
<version>3.3.9</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
二、Spring中的依赖注入
接下来我们要来看一下Spring中的依赖注入的调用方式,该部分主要聊了两种Spring中的依赖注入的方式。一种是注解方式,这种方式也是常用的,另一种就是Java配置类的方式。当然在早期Spring版本中是使用xml进行依赖注入的,因为xml配置的繁琐以及不方便管理的一些特点,所以我们在工程中一般使用注解以及Java配置的形式。下方会给出注解以及Java配置的形式,并给出其使用场景。
1、使用注解实现依赖注入
本小部分,我们将使用注解来声明Spring中的Bean。主要是使用@Service注解来声明业务逻辑层(Service层)所使用的Bean,使用@Repository注解声明数据访问层(DAO层)使用的Bean,使用@Controller注解来声明展现层的Bean,使用@Component来注解组件的Bean。当然这几个注解其在底层的实现是大同小异的,其功能也是类似的,只是名称不同。
我们可以使用Spring提供的@Autowired来声明依赖注入的注入点,也可以使用JSR-330提供的@Inject或者JSR-250提供的@Resource注解声明注入点。下面就来看一下这些注解的使用方式。
(1) @Repository
下方代码片段就是使用@Repository注解来声明的Bean,在数据访问层会使用该注解来声明DAO层的Bean。稍后我们会使用到下方的RepositoryBean。
(2) @Service
下方是我们使用@Service来声明的Bean,在业务逻辑层,我们会使用到@Service注解进行Bean的声明。在下方代码段中,我们使用@Service声明ServiceBean后,在该类中,我们注入了RepositoryBean的对象。当然使用的是@Autowired来注解的依赖对象的注入点。也就是说,在运行时,会动态的给下方的repositoryBean分配一个RepositoryBean的对象。如下所示:
(3) @Component
@Component是用来声明组件的,也就是说你封装了一个组件,这个组件就是使用@Component来进行注解,使其可以被注入。下方就是使用了@Component注解声明的组件。稍后我们会在Controller中进行调用。
(4) @Controller
接下来我们就使用@Controller来声明我们的控制器,下方的ControllerBean就是我们的控制器类,当然此处我们使用@Controller进行的注解。然后在该控制器类中,我们使用了@Autowired注解来注入ServiceBean和ComponentBean的对象,然后在下方相应的方法中进行了使用。
(5)、创建Spring的配置文件
接下来我们将创建Spring的配置文件,因为Spring可以通过此配置文件读取一些上下文的信息。当然,Spring的配置文件其实就是一个Java类,然后我们使用@Configuration进行修饰即可。而@ComponentScan("包名")负责指定组件所在的包,也就是说设置完该项后,Spring会自动扫描该包下的@Component、@Service、@Repository、@Controller这些注解。
(6)、创建Main函数进行测试
上面一些列的Bean已经创建完毕,接下来,我们要创建我们测试用的Main函数了。首先我们使用注解配置上下文AnnotationConfigApplicationContext对象来从Java的配置文件中获取Spring的上下文。然后获取Controller Bean,下方是调用Controller Bean的相应的方法。最后再将调用的资源关闭掉即可。
(7)、运行结果
上述实现完Main方法后,接下来我们就可以对其运行并看起运行效果了。具体运行结果如下所示:
2、Java配置
上面一部分是使用Spring中提供的相关注解来声明的各种类型的Bean。接下来我们就在Spring的配置文件来声明相关的Bean,当然在Java配置文件中声明的Bean一般是全局的,也就是说一些Bean要定义成全局的对象的话,我们就在Java配置中来进行Bean的声明。例如一些公共的组件的Bean,我们就可以将其放入到Java的配置文件中。接下来我们就来看一下Spring配置文件中是如何来声明Bean的。
(1)、创建Java配置使用的类
首先我们来创建一个类,此处我们命名为JavaConfigBean。然后我们要在Spring的配置文件中将其声明为Bean。我们可以看出,下方类就是一个普通的Java类,该类中并没有使用任何的注解进行修饰。
(2)、在Spring配置文件中声明Bean
接下来我们将会在Spring的配置文件中使用@Bean注解将上述的JavaConfigBean声明为Bean对象。下方代码段就是Spring配置文件中的内容,其中的createJavaConfigBean()方法负责生成上述类的对象。其中我们使用@Bean注解声明该方法,该方法会返回JavaConfigBean类的对象。在使用JavaConfigBean的对象时,会将下方生成的对象注入到相应的点上。
(3)、创建依赖JavaConfigBean的Controller
接下来我们就来创建一个Controller类,在该类中我们来使用JavaConfigBean的对象。下方就是我们创建的ControllerBean的类中的具体内容,其中使用了@Autowired注解来声明的注入点,如下所示:
(4)、创建Main函数以及测试结果
接下来我们就该创建一个Main函数来进行测试了。在Main函数中依然是调用了ControllerBean的相关方法,如下所示:
三、面向切面编程--(Aspect Oriented Programming)
在前段时间发布的博客中,我们已经使用了ObjC的Runtime来演示了AOP编程的实现原理。在Java中利用了Java的“反射机制”来实现的。其实在运行时,我们通过方法体的交换就可以实现AOP编程。Spring中的AOP编程也不例外,也是通过方法交换来实现的,本篇博客,我们就来看一下Spring框架中是如何使用AOP编程的。本部分给出了Spring框架中两种AOP编程的调用方案,一种是基于注解式的拦截方式,另一种是基于方法式的拦截。
下方将会分别给出这两种AOP编程实现的两种方式。在基于注解式的拦截方式中,我们需要为切点方法添加注解,而方法式拦截则不需要在切点方法上做任何操作。
1、引入Spring的AOP依赖包和AspectJ依赖包
下方的XML内容就是我们要在pom.xml添加的相关依赖配置,下方我们添加了spring-aop以及aspectj的依赖。aspectj也是一个Java的面向切面编程的依赖包。我们要做的东西也依赖于aspectj。具体的依赖包的引入如下所示:
<!-- spring aop支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.6.RELEASE</version>
</dependency> <!-- aspectj支持 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
2、基于注解的AOP
接下来我们将实现基于注解式的AOP实现,下方我们将创建AOP使用的注解,切面类、被切面的Controller、Spring配置文件以及测试用的Main函数。下方是基于注解的AOP的具体实现。
(1)、创建AOP使用的注解
首先我们先创建一个注解,该注解会在切入点中进行使用。选择我们相应的package,然后右键单击->New->Annotation来创建一个注解。
该注解中的内容比较简单,具体内容如下所示:
package com.zeluli.aop.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
}
(2)、创建切面切入的Controller
接下来我们就来创建一个切面切入的Controller,此处我们将该类命名为AnnotationController。在该Controller中相应方法上,我们使用上述我们创建的@Action注解来进行声明,将其声明为我们切面的切入点。具体如下所示:
(3)、编写切面类
定义好声明切点的注解@Action以及被切入的Controller后,接下来,我们就该创建切面类了。下方创建的LogAspect类就是用来切入AnnotationController类的切面类。具体内容如下所示。
我们使用@Aspect注解将LogAspect类声明为切面,然后使用@Component注解将其声明为组件。之所以将其声明为组件,是因为我们可以将该切面切入到好多类中。然后我们使用@Pointcut注解来指定切入点,@Pointcut参数就是我们上面创建的注解@Action。也就是说使用@Action修饰的方法就是我们的切入点。使用@Before注解来声明在切点之前执行的方法,使用@After注解来声明在切点之后执行的方法。下方就是LogAspect类的具体内容。
(4)、创建Spring的配置文件
接着我们要创建配置类,在配置类中我们要开启AspectJ的自动代理,如下所示。
(5)、创建Main函数进行测试
接下来,我们就开始测试了。Main方法比较简单,与上面的Main方法大同小异。主要是调用AnnotationConfigApplicationContext来从配置文件中加载上下文,然后根据上下文获取AnnotationController的对象,然后调用testMethod()方法,最后将上下文进行关闭即可。
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext aopContext = new AnnotationConfigApplicationContext(AopConfig.class);
AnnotationController controller = aopContext.getBean(AnnotationController.class);
controller.testMethod();
aopContext.close();
}
}
下方截图就是上述Main方法的运行结果,可见,在testMethod()方法调用之前会执行切片的@Before方法,testMethod()方法执行之后会执行@After方法。具体结果如下所示:
3、基于方法的AOP
上面我们聊了基于注解拦截的切面,接下来我们就来看一下基于方法的切面。也就是说在该部分,我们不会创建注解。直接创建LogAspect切面即可。下方这个LogAspect切面就是基于方法的切面。其中在@Before或者@After注解后边跟着一串字符串,该字符串就是切入点所在类。如下所示。
上述切面的运行效果与注解切面的运行效果一致,在此就不做过多赘述了。
本篇博客就先到此,上述相关代码在github上的分享地址为:https://github.com/lizelu/SpringDemo
JavaEE开发之Spring中的依赖注入与AOP的更多相关文章
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- JavaEE开发之Spring中Bean的作用域、Init和Destroy方法以及Spring-EL表达式
上篇博客我们聊了<JavaEE开发之Spring中的依赖注入以及AOP>,本篇博客我们就来聊一下Spring框架中的Bean的作用域以及Bean的Init和Destroy方法,然后在聊一下 ...
- JavaEE开发之Spring中的多线程编程以及任务定时器详解
上篇博客我们详细的聊了Spring中的事件的发送和监听,也就是常说的广播或者通知一类的东西,详情请移步于<JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换&g ...
- JavaEE开发之Spring中的条件注解组合注解与元注解
上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...
- JavaEE开发之Spring中的条件注解、组合注解与元注解
上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...
- JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换
本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...
- JavaEE开发之SpringMVC中的静态资源映射及服务器推送技术
在上篇博客中,我们聊了<JavaEE开发之SpringMVC中的自定义拦截器及异常处理>.本篇博客我们继续的来聊SpringMVC的东西,下方我们将会聊到js.css这些静态文件的加载配置 ...
- JavaEE开发之SpringMVC中的自定义消息转换器与文件上传
上篇博客我们详细的聊了<JavaEE开发之SpringMVC中的静态资源映射及服务器推送技术>,本篇博客依然是JavaEE开发中的内容,我们就来聊一下SpringMVC中的自定义消息转发器 ...
- JavaEE开发之SpringMVC中的自定义拦截器及异常处理
上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...
随机推荐
- 第二章:在HTML中使用JavaScript
1:在使用<script>嵌入JavaScript代码死,记住不要在代码中的任何地方出现"</script>"字符串 例如,浏览器在加载下面所示代码时就会产 ...
- java系列笔记---正则表达式(2)
正则表达式 说真的正则表达式真不好写,当我收集资料准备开始写的时候,发现收集的东西越来越多范围也越来越广,我文章的前提就是文章要清晰, 在缕清自己思路之后,我从先简后难的方式来写有关正表达式,你们如果 ...
- 简单三层分页aspnetpager控件(欢迎指点)
首先添加引用AspNetpager.dll(将.dll文件放在bin中进行引用) 接着添加<%@ Register Assembly="AspNetPager" Namesp ...
- SQL极限函数limit()详解<分页必备>
limit含义: limit英语中的含义是限制,限定的意思.小日本曾上映过一个电影就是叫limit是由漫画改编的电影,剧情很变态,但不可否认小日本由于地狭人稠的原因,在观念上的资源危机意识还是很强的哈 ...
- CI Weekly #14 | 如何搭建合适的持续交付开发流程?
时隔 10 个月,flow.ci 开始正式收费上线.为感谢对我们的内测支持,所有内测用户可继续免费使用基础版 30 天,截止至 3 月 15 日失效.欢迎随时告诉我们你对收费版 flow.ci 的反馈 ...
- 3553: [Shoi2014]三叉神经树(树链剖分)
这道题特别恶心,首先我们可以发现更改的就是出现连续的一或二,那么就用线段树+树链剖分找到这个范围 想到是不难想,就是打起来恶心罢了= = CODE: #include<cstdio> #i ...
- java 计算源码的行数
import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOExcepti ...
- Weinre 远程调试移动端页面
Weinre 是一款远程调试工具,使用JS编写, 可以让我们在电脑上直接调试运行在手机上的远程页面,当你的代码已经发布上线,这时候出现了问题,Weinre就可以帮你调试. 调试场景 调试页面在手机上. ...
- Entity Framework+SQLite+DataBaseFirst
Entity Framework+Sqlite+DataBaseFirst 本篇主要是说明在vs中配置Sqlite,及使用Entity Framework DataBaseFirst模式. 如果没有下 ...
- WebSocket浅析(一):实现群聊功能
首先WebSocket打破了传统的web请求响应模式,实现管道式的实时通信,并且可以持续连接. 相对于传统 HTTP 每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket 是类似 So ...