通过spring aop的方法来计算方法执行时间,并通过自定义注解来限制被动态代理的方法
一、自定义注解TimeLogger
package com.learn.frame.spring.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeLogger {
String value() default "";
}
自定义注解的理解:
JDK5开始,java增加了对元数据(MetaData)的支持,怎么支持?答:通过Annotation(注解)来实现。Annotation提供了为程序元素设置元数据的方法。元数据:描述数据的数据。
二、Aspect切面类
package com.learn.frame.spring.aspect;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.iframe.springmvc.bean.User;
import com.learn.frame.spring.annotation.TimeLogger;
import com.learn.frame.spring.utils.DebugLogger;
@Component
@Aspect
public class LoggerAspectJ {
//@annotation:用于匹配当前执行方法持有指定注解的方法
//@within(注解类型全限定名)匹配所有持有指定注解的类里面的方法, 即要把注解加在类上. 在接口上声明不起作用
@Pointcut(value="@within(org.springframework.stereotype.Service) && @annotation(com.learn.frame.spring.annotation.TimeLogger)")
public void pointCut(TimeLogger){}
//通知中传递参数
@Around(value = "pointCut(timeLogger)")
public Object printTimeLogger(ProceedingJoinPoint pjp) throws Throwable{
Long start = System.currentTimeMillis();
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
//Method method = methodSignature.getMethod(); //获得是接口的方法
Object target = pjp.getTarget();
Method currentMethod = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());//当前执行类的方法
TimeLogger timeLogger2 = currentMethod.getAnnotation(TimeLogger.class);
Object obj = pjp.proceed();
Long end = System.currentTimeMillis();
DebugLogger.log("################{} : {} ms ##############" ,timeLogger2.value(),(end-start));
return obj;
}
}
扫描二维码关注公众号,回复:
2269202 查看本文章
@annotation:用于匹配当前执行方法持有指定注解的方法
@within:用于匹配所以持有指定注解类型内的方法
使用参数传递改良上述代码,
package com.learn.frame.spring.aspect;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.iframe.springmvc.bean.User;
import com.learn.frame.spring.annotation.TimeLogger;
import com.learn.frame.spring.utils.DebugLogger;
@Component
@Aspect
public class LoggerAspectJ {
//@annotation:用于匹配当前执行方法持有指定注解的方法
//@within(注解类型全限定名)匹配所有持有指定注解的类里面的方法, 即要把注解加在类上. 在接口上声明不起作用
@Pointcut(value="@within(org.springframework.stereotype.Service) && @annotation(timeLogger)")
public void pointCut(TimeLogger timeLogger){}
//通知中传递参数
@Around(value = "pointCut(timeLogger)")
public Object printTimeLogger(ProceedingJoinPoint pjp,TimeLogger timeLogger) throws Throwable{
Long start = System.currentTimeMillis();
Object obj = pjp.proceed();
Long end = System.currentTimeMillis();
DebugLogger.log("################{} : {} ms ##############" ,timeLogger.value(),(end-start));
return obj;
}
}
三、Service 使用自定义注解
package com.learn.frame.spring.service.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Service;
import com.learn.frame.spring.annotation.TimeLogger;
import com.learn.frame.spring.po.User;
import com.learn.frame.spring.service.UserService;
@Service("userService2")
public class UserServiceImpl2 implements UserService{
@Autowired //按类型自动匹配
private JdbcDaoSupport template; //整合spring jdbcTemplate
@TimeLogger("how to do")
@Override
public User searchUserById(int id) throws Exception {
String sql = "select * from user where id = ?";
System.out.println(sql);
return template.getJdbcTemplate().queryForObject(sql, new Object[]{id}, new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setCd(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setBirthday(rs.getDate("birthday"));
user.setAddress(rs.getString("address"));
return user;
}
});
}
}
四、Test
package com.learn.frame.spring.aspect;
import org.junit.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.learn.frame.spring.po.User;
import com.learn.frame.spring.service.UserService;
import com.learn.frame.spring.utils.DebugLogger;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring/applicationContext.xml"}) //加载配置文件
public class AspectJTest {
@Autowired
@Qualifier("userService2")
UserService userService;
//Test is not an annotation type 不能讲测试类命名为Test
@Test
public void test() throws Exception{
User user = userService.searchUserById(2);
DebugLogger.log(user.toString());
}
}
结果:
################@com.learn.frame.spring.annotation.TimeLogger(value=how to do) : 15 ms ##############