在Spring中怎么拦截自定义的注解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Spring中怎么拦截自定义的注解相关的知识,希望对你有一定的参考价值。

步骤4:在Action或者其他service类中
@AnnotationsUtil(format="#.00D")
public Double getTestDouble()
return testDouble;


步骤5:启动项目,当执行到方法:getTestDouble()时,不会被Spring拦截,也不会进入到解析注解的前置通知工具类:ParseAnnoAdivceUtil处理注解信息。

期望得到的效果是:当运行到某被定义注解的方法(如:getTestDouble())时,自动被拦截,并进入到解析注解的前置通知工具类:ParseAnnoAdivceUtil处理注解信息,修改被注解的方法的值...
求高手解答...谢谢...
步骤2:定义解析注解类
/**
* 解析注解的前置通知工具类
* @author E.FLY
* @date 2012-11-20
* @time 上午10:46:28
*/
public class ParseAnnoAdivceUtil implements MethodBeforeAdvice
@Override
public void before(Method method, Object[] parems, Object impl)throws Throwable


@Aspect
@Component//加上这个
public class MyInterceptor
@Pointcut("execution(public * com.newer.service.imp.PersonServiecBean.save*(..))")
private void anyMethod()

@After(value="anyMethod()")
public void doAccess()
System.out.println("前置通知!!");



<bean id="personService" class="com.newer.service.impl.PersonServiecBean"/>
配置里面把myInterceptor去掉

如果还不行 干脆用xml的形式
<bean id="personService" class="com.newer.servic e.impl.PersonServiecBean"/>
<bean id="myInterceptor" class="com.newer.service.MyInterceptor" />

<aop:config>

<aop:aspect id="logAspect" ref="myInterceptor">
<aop:before method="before" pointcut=("execution(public * com.newer.service.imp.PersonServiecBean.save*(..))") />
</aop:aspect>

</aop:config>
参考技术A 比如你想 执行a方法 那么就在a上面添加注解b 路径写成。。。.do?b就行了

spring 中如何进行方法的判定

我要在Spring中后置拦截很多类中的很多对数据库操作的方法,以便在日志中记录。但是怎么才能拦截一个类中所有方法呢,根据method参数判定呢(if(method=doAction()))这样好像不行啊,怎样指定目标方法???正则表达式好像也不大好用。

方法一 拦截指定的方法可以启用@AspectJ支持 这个方法面需要在原有代码中加入标注。具体做法可以参考Spring-Reference_zh_CN.chm。可以到满江红开源社区下载。
方法二 如果你是想拦截所有的类的doAction 方法你可以写一个接口,接口中声明doAction 方法,让所有类去实现这个接口,然后调用的时候转化为接口调用,这样就能拦截所有的doAction 方法了。这种做法也是需要修改代码。
方法三 最简单的方法 直接在拦截方法中过滤
写个例子吧
public void before(Method method, Object[] args, Object target)
throws Throwable
if(method.getName()="doAction")
//TODO: do something

参考技术A 用AspectJ的语法就可以了! 参考技术B 1、Spring只支持方法拦截,也就是说,只能在方法的前后进行拦截,而不能在属性前后进行拦截。
2、Spring支持四种拦截类型:目标方法调用前(before),目标方法调用后(after),目标方法调用前后(around),以及目标方法抛出异常(throw)。
3、前置拦截的类必须实现MethodBeforeAdvice接口,实现其中的before方法。
4、后置拦截的类必须实现AfterReturningAdvice接口,实现其中的afterReturning方法。
5、前后拦截的类必须实现MethodInterceptor接口,实现其中的invoke方法。前后拦截是唯一可以控制目标方法是否被真正调用的拦截类型,也可以控制返回对象。而前置拦截或后置拦截不能控制,它们不能影响目标方法的调用和返回。
但是以上的拦截的问题在于,不能对于特定方法进行拦截,而只能对某个类的全部方法作拦截。所以下面引入了两个新概念:“切入点”和“引入通知”。
6、”切入点“的定义相当于更加细化地规定了哪些方法被哪些拦截器所拦截,而并非所有的方法都被所有的拦截器所拦截。在ProxyFactoryBean的属性中,interceptorNames属性的对象也由拦截(Advice)变成了引入通知(Advisor),正是在Advisor中详细定义了切入点(PointCut)和拦截(Advice)的对应关系,比如常见的基于名字的切入点匹配(NameMatchMethodPointcutAdvisor类)和基于正则表达式的切入点匹配(RegExpPointcutAdvisor类)。这些切入点都属于”静态切入点“,因为他们只在代理创建的时候被创建一次,而不是每次运行都创建。

下面我们进行实例的开发

首先创建业务接口:

package AdvisorTest;

public interface Shopping ...
public String buySomething(String type);
public String buyAnything(String type);
public void testException();


下面是业务实现类,我们的通知就是以这些实现类作为切面,在业务方法前后加入我们的通知代码

package AdvisorTest;

public class ShoppingImpl implements Shopping ...
private Customer customer;
public Customer getCustomer() ...
return customer;

public void setCustomer(Customer customer) ...
this.customer = customer;

public String buySomething(String type) ...
System.out.println(this.getCustomer().getName()+" bye "+type+" success");
return null;


public String buyAnything(String type) ...
System.out.println(this.getCustomer().getName()+" bye "+type+" success");
return null;


public void testException()...
throw new ClassCastException();



(1)前置通知

配置了前置通知的bean,在执行业务方法前,均会执行前置拦截器的before方法

package AdvisorTest;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
//前置通知
public class WelcomeAdvice implements MethodBeforeAdvice ...

public void before(Method method, Object[] args, Object obj)
throws Throwable ...
String type=(String)args[0];
System.out.println("Hello welcome to bye "+type);





(2)后置通知

配置了后置通知的bean,在执行业务方法后,均会执行后置拦截器的afterReturnning方法 package AdvisorTest;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
//后置通知
public class ThankYouAdvice implements AfterReturningAdvice ...

public void afterReturning(Object obj, Method method, Object[] arg1,
Object arg2) throws Throwable ...

String type=(String)arg1[0];
System.out.println("Hello Thankyou to bye "+type);




(3)环绕通知

配置了环绕通知的bean,在执行业务方法前后,均会执行环绕拦截器的invoke方法

需要注意的是必须调用目标方法,如不调用,目标方法将不被执行

package AdvisorTest;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MethodAdvisor implements MethodInterceptor ...

public Object invoke(MethodInvocation invocation) throws Throwable ...
String str=(String)invocation.getArguments()[0];
System.out.println("this is before"+str+" in MethodInterceptor");
Object obj=invocation.proceed(); //调用目标方法,如不调用,目标方法将不被执行
System.out.println("this is after"+str+" in MethodInterceptor");
return null;




(4)异常通知

ThrowsAdvice是一个标示接口,我们可以在类中定义一个或多个,来捕获定义异常通知的bean抛出的异常,并在抛出异常前执行相应的方法

public void afterThrowing(Throwable throwa)或者

public void afterThrowing(Method method,Object[] args,Object target,Throwable throwable)

package AdvisorTest;

import org.springframework.aop.ThrowsAdvice;

public class ExceptionAdvisor implements ThrowsAdvice ...
public void afterThrowing(ClassCastException e)...
System.out.println("this is from exceptionAdvisor");



配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
<bean id="customer" class="AdvisorTest.Customer">
<constructor-arg index="0">
<value>gaoxiang</value>
</constructor-arg>
<constructor-arg index="1">
<value>26</value>
</constructor-arg>
</bean>

<bean id="shoppingImpl" class="AdvisorTest.ShoppingImpl">
<property name="customer">
<ref local="customer"/>
</property>
</bean>

<!-- 前置通知 -->
<bean id="welcomeAdvice" class="AdvisorTest.WelcomeAdvice"/>
<bean id="welcomeAdviceShop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>AdvisorTest.Shopping</value>
</property>
<property name="target">
<ref local="shoppingImpl"/>
</property>
<property name="interceptorNames">
<list>
<value>welcomeAdvice</value>
</list>
</property>

</bean>

<!-- 后置通知 -->
<bean id="thankyouAdvice" class="AdvisorTest.ThankYouAdvice"/>
<bean id="thankyouAdviceShop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>AdvisorTest.Shopping</value>
</property>
<property name="target">
<ref local="shoppingImpl"/>
</property>
<property name="interceptorNames">
<list>
<value>thankyouAdvice</value>
</list>
</property>

</bean>

<!-- 环绕通知 -->
<bean id="methodAdvice" class="AdvisorTest.MethodAdvisor"/>
<bean id="methodAdviceShop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>AdvisorTest.Shopping</value>
</property>
<property name="target">
<ref local="shoppingImpl"/>
</property>
<property name="interceptorNames">
<list>
<value>methodAdvice</value>

</list>
</property>
</bean>

<!-- 异常通知 -->
<bean id="exceptionAdvice" class="AdvisorTest.ExceptionAdvisor"/>
<bean id="exceptionAdviceShop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>AdvisorTest.Shopping</value>
</property>
<property name="target">
<ref local="shoppingImpl"/>
</property>
<property name="interceptorNames">
<list>
<value>exceptionAdvice</value>

</list>
</property>
</bean>
</beans>

测试代码:

package AdvisorTest;

import java.io.File;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

public class TestAdvisor ...

public static void main(String[] args) ...

String filePath=System.getProperty("user.dir")+File.separator+"AdvisorTest"+File.separator+"hello.xml";

BeanFactory factory=new XmlBeanFactory(new FileSystemResource(filePath));

Shopping shopping=null;
System.out.println("不使用任何通知");
shopping=(Shopping)factory.getBean("shoppingImpl");
shopping.buySomething("something");
shopping.buyAnything("anything");

System.out.println("使用前置通知");
shopping=(Shopping)factory.getBean("welcomeAdviceShop");
shopping.buySomething("something");
shopping.buyAnything("anything");

System.out.println("使用后置通知");
shopping=(Shopping)factory.getBean("thankyouAdviceShop");
shopping.buySomething("something");
shopping.buyAnything("anything");

System.out.println("使用环绕通知");
shopping=(Shopping)factory.getBean("methodAdviceShop");
shopping.buySomething("something");
shopping.buyAnything("anything");

System.out.println("使用异常通知");
shopping=(Shopping)factory.getBean("exceptionAdviceShop");
shopping.testException();




运行结果一目了然:

不使用任何通知
gaoxiang bye something success
gaoxiang bye anything success
使用前置通知
Hello welcome to bye something
gaoxiang bye something success
Hello welcome to bye anything
gaoxiang bye anything success
使用后置通知
gaoxiang bye something success
Hello Thankyou to bye something
gaoxiang bye anything success
Hello Thankyou to bye anything
使用环绕通知
this is beforesomething in MethodInterceptor
gaoxiang bye something success
this is aftersomething in MethodInterceptor
this is beforeanything in MethodInterceptor
gaoxiang bye anything success
this is afteranything in MethodInterceptor
使用异常通知
this is from exceptionAdvisor
参考技术C 根据action的名字来判断撒 没必要根据方法名来判断

以上是关于在Spring中怎么拦截自定义的注解的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security自定义拦截器

springboot怎么让自定义的拦截器优先于pagehelper执行

springCloud+自定义注解+自定义配置拦截器

Java自定义注解的定义与使用

Spring Boot 自定义注解支持EL表达式(基于 MethodBasedEvaluationContext 实现)

spring AOP 和自定义注解进行身份验证