上篇博客咱们系统的聊了《JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的建立》,并在以前的博客中咱们聊了依赖注入的相关东西,而且使用Objective-C的Runtime来实现了ObjC中的依赖注入,相关博客请参考《类比Spring框架来实现OC中的依赖注入》。固然以前的博客也是使用了ObjC的Runtime的东西来实现了ObjC中的“面向切面”编程的实现方式,相关博客请移步于《ObjC中的AOP--面向切面编程》。本篇博客咱们就来看一下Spring框架中的依赖注入以及AOP编程的几种方式,固然其实现方式是使用了Java的“反射机制”,也就相似于ObjC中的Runtime了。html
今天博客中所使用的Spring版本是4.3.6.RELEASE,是目前比较新的Spring版本了。而Java的版本使用的是Java8了。上篇博客咱们主要聊了相关环境的建立与配置,本篇博客将不会对环境配置这些东西进行详细的叙述。本篇博客主要聊了Spring框架中的依赖注入的实现方式,主要是经过注解以及Java配置来实现的,固然还会聊些AOP的东西。java
1、快速建立Mava管理的Spring工程git
由于本篇博客是讨论关于Spring的东西,因此咱们就不建立WebApp的工程了。咱们使用Spring来快速的建立一个Maven管理的工程。以下所示找到File->New->Maven Project选项来建立一个新的Maven Project,具体以下所示:github
下方咱们选择建立一个简单的Maven工程,跳过模板的选择。上篇博客咱们在建立Maven工程时,是没有选择下方这个选项的,而后咱们选择了一个WebApp的模板。而本篇博客,咱们不须要WebApp的模板,只须要一个简单的Maven工程便可。spring
接着输入组织名和工程名,以下所示。点击Finish便可完成Maven简单工程的建立。apache
下面就是咱们建立好的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>
2、Spring中的依赖注入maven
接下来咱们要来看一下Spring中的依赖注入的调用方式,该部分主要聊了两种Spring中的依赖注入的方式。一种是注解方式,这种方式也是经常使用的,另外一种就是Java配置类的方式。固然在早期Spring版本中是使用xml进行依赖注入的,由于xml配置的繁琐以及不方便管理的一些特色,因此咱们在工程中通常使用注解以及Java配置的形式。下方会给出注解以及Java配置的形式,并给出其使用场景。函数
一、使用注解实现依赖注入
本小部分,咱们将使用注解来声明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方法后,接下来咱们就能够对其运行并看起运行效果了。具体运行结果以下所示:
二、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的相关方法,以下所示:
3、面向切面编程--(Aspect Oriented Programming)
在前段时间发布的博客中,咱们已经使用了ObjC的Runtime来演示了AOP编程的实现原理。在Java中利用了Java的“反射机制”来实现的。其实在运行时,咱们经过方法体的交换就能够实现AOP编程。Spring中的AOP编程也不例外,也是经过方法交换来实现的,本篇博客,咱们就来看一下Spring框架中是如何使用AOP编程的。本部分给出了Spring框架中两种AOP编程的调用方案,一种是基于注解式的拦截方式,另外一种是基于方法式的拦截。
下方将会分别给出这两种AOP编程实现的两种方式。在基于注解式的拦截方式中,咱们须要为切点方法添加注解,而方法式拦截则不须要在切点方法上作任何操做。
一、引入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>
二、基于注解的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方法。具体结果以下所示:
三、基于方法的AOP
上面咱们聊了基于注解拦截的切面,接下来咱们就来看一下基于方法的切面。也就是说在该部分,咱们不会建立注解。直接建立LogAspect切面便可。下方这个LogAspect切面就是基于方法的切面。其中在@Before或者@After注解后边跟着一串字符串,该字符串就是切入点所在类。以下所示。
上述切面的运行效果与注解切面的运行效果一致,在此就不作过多赘述了。
本篇博客就先到此,上述相关代码在github上的分享地址为:https://github.com/lizelu/SpringDemo