`
yangshen998
  • 浏览: 1244744 次
文章分类
社区版块
存档分类
最新评论

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 的配置文件中删除,该功能没有收到任何影响

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics