Spring AOP 自定义注解

通过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提供了为程序元素设置元数据的方法。元数据描述数据的数据。

Java 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 ##############


猜你喜欢

转载自blog.csdn.net/zl_momomo/article/details/80674571