spring中有很多概念和名词,其中有一些名字不同,但是从功能上来看总感觉是那么的相似,比如过滤器、拦截器、aop等。
过滤器filter、spring mvc拦截器Interceptor 、面向切面编程aop,实际上都具有一定的拦截作用,都是拦截住某一个面,然后进行一定的处理。
在这里主要想着手的是aop,至于他们的比较,我想等三个都一一了解完了再说,因此这里便不做过多的比较。
在我目前的项目实践中,只在一个地方手动显示的使用了aop,那便是日志管理中对部分重要操作的记录。
据我目前所知,aop拦截一般都是用在具体的方法上,或者说是具体的某一类方法,我所用过的实现方式有两种,一种是直接代码声明,一种是在xml文件中配置。
由于我目前实际开发的项目都是使用spring+spring mvc的架构,然后使用maven管理,然后junit测试。因此我自己几乎所有的个人项目也都是采用这些架构和项目管理工具,在这个理解aop的小项目中,自然也是这样,依赖包如下:
<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>springTest</groupId> <artifactId>aopTest</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.0.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.0.3.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.4</version> </dependency> </dependencies> </project>
第一种方式,Java代码声明:
这里实例中,我要声明一个aop来拦截dao层中的get开头的所有方法,首先建一个dao以及简单的额imp实现:
dao接口如下:
package com.ck.aopTest.dao; import com.ck.aopTest.model.UserModel; public interface MyAopDao { public void getUser(); public void getName(UserModel user); public void addUser(); }
简单的实现:
package com.ck.aopTest.dao.impl; import org.springframework.stereotype.Repository; import com.ck.aopTest.dao.MyAopDao; import com.ck.aopTest.model.UserModel; @Repository public class MyAopDaoImpl implements MyAopDao { @Override public void getUser() { System.out.println("这是我的aop测试dao方法一"); } @Override public void getName(UserModel userModel) { System.out.println("这是我的aop测试dao方法二"); } @Override public void addUser() { System.out.println("这是我的aop测试dao方法三"); } }
然后声明一个aop:
package com.ck.aopTest.aop; import java.util.Date; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import com.ck.aopTest.model.UserModel; @Aspect @Component public class MyAop { @Pointcut("execution(public * com.ck.aopTest.dao.impl.*.get*(..))") private void aopTest() { } @Before("aopTest()") public void before() { System.out.println("调用dao方法前拦截" + new Date().getTime()); } @After("aopTest()" + "&&args(user)") public void after(UserModel user) { System.out.println(user.getName()); System.out.println("调用dao方法之后拦截" + new Date().getTime()); } @Around("aopTest()") public void around(ProceedingJoinPoint pdj) { System.out.println("调用dao之前的环绕拦截" + new Date().getTime()); try { pdj.proceed(); } catch (Throwable e) { e.printStackTrace(); } System.out.println("调用dao之后的环绕拦截" + new Date().getTime()); } }
上述代码便是用java声明aop的核心代码,其中注解@Aspect的作用的就是告诉spring这是一个aop类,然后@Component就不用多说了,告诉spring这是一个需要扫描的类。
再往下,@Pointcut(“execution(public * com.ck.aopTest.dao.impl..get(..))”)正式声明需要拦截的切面,@Pointcut以及后边的额execution是固定的写法,execution后括号内的内容便是具体的切面,这里的意思是拦截所有public的任何返回值或者void的、命名空间是com.ck.aopTest.dao.impl下边的所有的类中的所有get开头的拥有任意多个参数的方法。
简单点说也就是当任何调用了com.ck.aopTest.dao.impl这个包中任何类中的get开头的方法,便会激活这个aop。
而紧接着上边这一段,我们看到了一个private void aopTest() 空的方法,实际上这个方法的作用是为这个aop切面声明一个名字,便于使用,也便于在多个aop切面时正常区分。
再后边的@Before、@After、@Around便是三个可选拦截方式,见名之意,分别是在上边声明的切面指明的方法调用之前执行、调用之后执行、以及环绕执行,调用之前和调用之后比较好理解,环绕的意思是在调用之前和之后都执行一定的逻辑。
从代码中可以看出,pdj.proceed();之前和之后各打印了两行数据,pdj.proceed();就代表了继续执行,如果是了解filter的应该很容易想到这个方法实际上和chain.doFilter很像,可以理解成放行。
在这三个注解之后需要指定要使用的切面,即@Pointcut声明的切面,指定名称就行。
从代码中可以看到有一个地方后边加了“&&args(UserModel user)”,意思是指定形参,也就是说指定的切面中有效方法的参数,例如上边dao中的getName方法有一个UserModel类型的参数,这里便可以使用。
主要代码写好了,接下来还有个必不可少的步骤,既然是spring项目,是spring的aop,那么自然需要配置spring文件,指明需要spring管理的包:
<?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:context="http://www.springframework.org/schema/context" " xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.ck.aopTest.*" /> </beans>
为了验证这里的aop是否真的有效,我写了一个junit测试:
package com.ck.aopTest.test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.ck.aopTest.dao.MyAopDao; import com.ck.aopTest.model.UserModel; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring.xml") public class AopTest { @Autowired private MyAopDao myAopDao; @Test public void aopTest2() { UserModel user = new UserModel(); myAopDao.getName(user); } }
按理说,这里运行测试方法后应该打印出很多条输出,但是遗憾的是结果只是打印出了dao中的一条输出,原因是spring配置中并没有启用aop,正确的配置应该是下边这样:
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <aop:aspectj-autoproxy /> <context:component-scan base-package="com.ck.aopTest.*" /> </beans>
我们需要再文件头加入
xmlns:aop=”http://www.springframework.org/schema/aop”
以及http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
除此之外,还要启用aop:
<aop:aspectj-autoproxy />
再次运行测试方法会看到控制台如下:
由此证明这个aop是有效的。
第二种方式,配置文件配置:
同样的,这里还是用之前的dao以及对应的impl,因此这段代码便不再重复,不一样的是具体的aop类如下:
package com.ck.aopTest.aop; public class MyAop2 { public void before2() { System.out.println("这是我的使用注解的aop,调用dao之前拦截"); } }
可以看到这个类实际上也是极致简单,普通类,普通方法,没有任何特别,然后我们要做的是在spring中配置:
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <aop:aspectj-autoproxy /> <bean id="myAop2" class="com.ck.aopTest.aop.MyAop2"></bean> <aop:config> <aop:pointcut expression="execution(public * com.ck.aopTest.dao.impl.*.add*(..))" id="aopTest1"/> <aop:aspect id="myAopTest2" ref="myAop2"> <aop:before method="before2" pointcut-ref="aopTest1"/> </aop:aspect> </aop:config> <context:component-scan base-package="com.ck.aopTest.*" /> </beans>
至于这里配置内容的具体解释,我想通过我对第一种方式的解释后,也没有太大必要再说,稍微一对比就会一清二楚。
同样的,这里只演示了before,至于after和round的配置应该也很容易就可以根据before推理出来。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
1. 前言 大家好,本小节重点介绍一个新知识 —— AOP 。作为入门的第一小节,我们需要理解 AOP 的概念,了解 AOP 的专业术语,明白它的作用。 那么,到底什么是 AOP ,它存在的意义是什么,在开发中扮演了一个什么样的角色呢? 随着疑问,开始本小节的内容。 2. 概述 2.1 AOP 的概念 AOP 并不是 Spring 框架的专属名称,它的全称是 Aspect Oriented Pro
本文向大家介绍Spring AOP面向切面编程实现及配置详解,包括了Spring AOP面向切面编程实现及配置详解的使用技巧和注意事项,需要的朋友参考一下 动态代理 特点 字节码随用随创建,随用随加载 作用 不用修改源码对方法增强 分类 基于接口的动态代理 基于子类的动态代理 创建 使用Proxy类中的newProxyInstance方法 要求 被代理类最少实现一个接口,没有则不能使用 newPr
我正在使用spring AOP拦截这些方法。我在spring配置文件中有以下配置。 方面类: 上面的方法不拦截私有方法?要求方面既拦截私有方法,又拦截公有方法,怎么办?
本文向大家介绍详解SpringBoot AOP 拦截器(Aspect注解方式),包括了详解SpringBoot AOP 拦截器(Aspect注解方式)的使用技巧和注意事项,需要的朋友参考一下 常用用于实现拦截的有:Filter、HandlerInterceptor、MethodInterceptor 第一种Filter属于Servlet提供的,后两者是spring提供的,HandlerInterc
概念 AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过动态代理等技术实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,也是 Hyperf 中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 用通俗的话来讲,就是
我试着用spring AOP写一个拦截器,拦截器会发现一个请求URL是否是书签,如果是的话会重定向到认证页面。代码段: public Object invoke(MethodInvocation invocation)抛出Throwable{Logger.Entering(This.GetClass().GetSimPlename(),“invoke”,invocation); 当我调试时,控件按