我想做一个将 用户操作记录保存到数据库的功能,利用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 的配置文件中删除,该功能没有收到任何影响
分享到:
相关推荐
自定义注解结合Hutool对SpringBoot接口返回数据进行脱敏 自定义注解结合Hutool对SpringBoot接口返回数据进行脱敏 自定义注解结合Hutool对SpringBoot接口返回数据进行脱敏 自定义注解结合Hutool对SpringBoot接口返回...
springboot工程通过自定义response注解、java反射机制、自定义java拦截器、自定义功能类实现WebMvcConfigurer接口等功能,实现自定义规范化返回数据结构。
NULL 博文链接:https://zyqwst.iteye.com/blog/2255560
自定义实现Autowired、Component、Configuration、SpringBootApplication注解,通过Java的反射完成。
工程介绍:SpringBoot项目脚手架,利用spring aop+java反射实现自定义注解校验参数 源码里有使用都例子在DemoContorller example1:校验userName参数必填 @CheckParams(notNull = true) private String userName;...
在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解。 Java1.5引入了注解,当前许多java框架中大量使用注解,如Hibernate、Jersey、Spring。注解作为程序的元数据嵌入到程序...
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 java.lang.annotation 包中。注解...
主要介绍了java注解之运行时修改字段的注解值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
1. 利用注解、反射和工厂模式设计一个简单的IoC容器 2. 该IoC容器包含3个注解和一个IoC容器类(AnnotationConfigApplicationContext),其定义如下: 注解 含义 @Component 标注Bean @Autowired 标注需要被注入的...
Spring容器的通俗理解及简单写法 手动写一个非常粗犷且简单的IOC容器。 用到了java的一些基础知识,比如说读取文件资源,反射,自定义注解的实现及使用等
里面使用Spring3.0 MVC,简单的注解和AOP,AOP改变了传进来的值,写了一个自定义注解,可在任意类中使用,不过自定义注解要结合反射才有效果
作用:通过元注解了解其他注解的使用特点,还可以自定义注解 2.元注解: 1. @Target @Target 作用 用来限制被修饰注解的使用范围,即注解可以在类的哪些成员上使用 ...
利用自定义注解和spring aop和java反射机制生成用户能够读懂的日志记录。如:用户张三在2013年9月27日17:00执行了用户管理模块的用户删除功能参数为(编号:123456)各位可根据需要写入数据库或者保存到文件。
面向对象:封装、继承、多态 ...注解:自定义注解、注解的应用等 数据库操作:JDBC、ORM框架、连接池等 常用的框架:Spring、SpringMVC、MyBatis、Hibernate等 分布式相关技术:Dubbo、Zookeeper、Redis、RocketMQ等
3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 3.5 Bean的生命周期 3.5.1 ...
1.注解和反射 1.注解 Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 Java 语言中的类、方法、变量、参数和包等都可以被标注。 内置的注解 作用在代码的注解是 @Override - 检查该方法是否...
3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 3.5 Bean的生命周期 3.5.1 ...
*第三阶段:java API:输入输出,多线程,网络编程,反射注解等,java的精华部分; *第四阶段:数据库SQL基础,包括增删改查操作以及多表查询; *第五阶段:JDBC编程:包括JDBC原理,JDBC连接库,JDBC API,...
分布式服务下的交易一致性原理及解决 分布式服务框架(dubbo+zookpeer) WEB高级前后台分离思维-懒加载无限级树形菜单 动态页面的静态化处理 大并发展示优化,动态页面的静态化 深入理解JDK动态代理本质 企业级高并发...
元注解、自定义注解、Java中常用注解使用、注解与反射的结合 Spring常用注解 JMS 什么是Java消息服务、JMS消息传送模型 JMX java.lang.management.*、 javax.management.* 泛型 泛型与继承、类型擦除、泛型中K T V E...