Spring 和 java 反射及自定义注解的问题解决!!

我想做一个将  用户操作记录保存到数据库的功能,利用java 的反射和自定义annotation 来实现,具体代码如下:

自定义annotation  类:



package com.util;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)    
@Retention(RetentionPolicy.RUNTIME)    
@Documented   
@Inherited  
public @interface MyAnnotation {
   
     String description() default "miss description";
   

}




UserServiceImp.java   带自定义注解的代码片段:
 @MyAnnotation(description="查找用户")
   public boolean findUser(User user) {
    // TODO Auto-generated method stub
    return userDao.findUserByUser(user);
}






切面类:

MyAspect.java



package com.util;

import java.lang.reflect.Method;
import java.util.Calendar;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;

import com.dao.LoggDao;
import com.model.Logg;
import com.model.User;




/*@Component("myAspect")*/
public class MyAspect {
  
    private HttpServletRequest request;
   private LoggDao loggDao;   
   
     public LoggDao getLoggDao() {
    return loggDao;
}

     
     @Resource
public void setLoggDao(LoggDao loggDao) {
    this.loggDao = loggDao;
}

    public void  dobefore(JoinPoint  jp) throws SecurityException, NoSuchMethodException{
    Class<?> targetClass=jp.getTarget().getClass();
        String methodName=jp.getSignature().getName();
   Method method=targetClass.getMethod(methodName,new Class[0]);

        MyAnnotation annotation=method.getAnnotation(MyAnnotation.class);
        String description=annotation.description();
       
       
        Calendar now = Calendar.getInstance();
        request=ServletActionContext.getRequest ();
        User user=(User)request.getSession().getAttribute("user");
         String logStr= "log Begining method: " 
                + jp.getTarget().getClass().getName() + "." 
                         + jp.getSignature().getName();
         
         
         Logg logg=new Logg();
         logg.setUser(user);
         logg.setFunction(jp.getSignature().getName());
         logg.setActionDate(now.getTime());
         logg.setMsg(logStr);
       // logg.setDescription(description);
         loggDao.addLog(logg);
         

     }
     
   
   
}



Spring  的配置文件:
<?xml version="1.0" encoding="UTF-8" ?>


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd  
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd  
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
  <context:annotation-config/>
  <context:component-scan base-package="com"/>


 
   

     <bean id ="dataSource"  class ="org.springframework.jdbc.datasource.DriverManagerDataSource" > 
         <property name="driverClassName" > 
             <value>com.mysql.jdbc.Driver</value> 
         </property > 
         <property name="url"> 
             <value> jdbc:mysql://localhost:3306/hibernate</value> 
         </property> 
         <property name ="username"> 
             <value>root</value > 
         </property > 
         <property name ="password" > 
             <value>xushigang1986</value> 
         </property > 
      
     </bean > 
    
      <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
         <property name="dataSource" ref="dataSource" />
         <property name="packagesToScan">
              <list>
                <value>com.model</value>
            
              </list>
         </property>
         <property name="hibernateProperties">
               <props>
                  <prop key="hibernate.dialect">
                      org.hibernate.dialect.MySQLDialect
                  </prop>
                  <prop key="hibernate.show_sql">true</prop>
                   <prop key="hibernate.hbm2ddl.auto">update</prop>
                 
              </props>   
          </property>
       </bean>
      
       <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
          <property name="sessionFactory" ref="sessionFactory">
          </property>
     </bean>
    
    
    

    <aop:config>
           <aop:aspect id="aopService" ref="myAspect">
               <aop:pointcut id="businessService" expression="execution(* com.service.imp.*.*(..))"/>
               <aop:before pointcut-ref="businessService" method="dobefore"/>
           </aop:aspect>
    </aop:config>
   
    <bean id="myAspect" class="com.util.MyAspect"></bean>

  
    <aop:aspectj-autoproxy proxy-target-class="true"/>

</beans>







UuserAction 类
该类是一个   pojo 类,在查资料时,说是如果Action 类继承了ActionSupport 类就不能实现这样的反射机制,所以我将UserAction 类改成了POJO 类。
网上说需要加 <aop:aspectj-autoproxy proxy-target-class="true"/> ,使Spring 来代替java SDK  来实现反射。在Spring 配置文件中,也加了这个配置。






启动Tomcat 并访问了
UserServiceImp类中的findUser(User user)方法后,
Tomcat 报错:

SEVERE: Servlet.service() for servlet default threw exception
java.lang.NoSuchMethodException: com.service.imp.UserServiceImp.findUser()
    at java.lang.Class.getMethod(Class.java:1605)
    at com.util.MyAspect.dobefore(MyAspect.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:609)
    at org.springframework.aop.aspectj.AspectJMethodBeforeAdvice.before(AspectJMethodBeforeAdvice.java:39)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:49)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
    at com.service.imp.UserServiceImp$$EnhancerByCGLIB$$7d56e110.findUser(<generated>)
    at com.action.LoginValidAction.validLogin(LoginValidAction.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:404)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:267)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:229)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:221)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
。。。。。




昨天已经试了一天,把网上所有能够用上的方法都试过了一遍,还是遇到上面的问题。

 

 

 

 

 

后来自己想了另外一条思路来解决这个问题:

Class<?> targetClass=jp.getTarget().getClass();
        String methodName=jp.getSignature().getName();          //获取到调用方法的方法名
   Method[] methods=targetClass.getMethods();         //获取该类下的所有方法
   Method method=null;
   for(int i=0;i<methods.length;i++){               
       boolean anMethod=methods[i].isAnnotationPresent(MyAnnotation.class);

                          // 判断某个方法是否具有  Myannotation 的自定义注解
                 if(anMethod){
          String methodStr=methods[i].toString();
    String methodName2=      methodStr.substring(0,methodStr.lastIndexOf("("));
    String methodName3=methodName2.substring(methodName2.lastIndexOf(".")+1);

                     //如果具有Myannotation 自定义注解,则取出该方法的方法名

      if(methodName3.equals(methodName)){

        //判断方法名和调用方法名是否相等
        System.out.println("aaaaaaaaaa");
        method=methods[i];
        //返回该方法,并跳出for 循环
        break;
       
    }
       }
      
   }
  

        MyAnnotation annotation=method.getAnnotation(MyAnnotation.class);
        String description=annotation.description();
       
       
        Calendar now = Calendar.getInstance();
        request=ServletActionContext.getRequest ();
        User user=(User)request.getSession().getAttribute("user");
         String logStr= "log Begining method: " 
                + jp.getTarget().getClass().getName() + "." 
                         + jp.getSignature().getName();
         
         
         Logg logg=new Logg();
         logg.setUser(user);
         logg.setFunction(jp.getSignature().getName());
         logg.setActionDate(now.getTime());
         logg.setMsg(logStr);
      logg.setDescription(description);
         loggDao.addLog(logg);

 

 

//通过进一步测试,该解决思路符合要求

 

 

 

 

 

 

 

 

另:继续求原来的解决方法,麻烦各位帮我看看问题出在哪里

 

 

通过进一步的测试,我将POJO 类型的Action 类改成了extends  ActionSupport   ,并将

<aop:aspectj-autoproxy proxy-target-class="true"/> 从Spring 的配置文件中删除,该功能没有收到任何影响

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值