基于注解的Spring AOP

Spring AOP 基本概念: http://hotstrong.iteye.com/blog/1330046
JoinPoint API: http://blog.csdn.net/a9529lty/article/details/7031070
1.定义注解
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation {

	String value() default "";

}

2.定义切面
/**
 *  切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现
 * @author donald
 *
 */
@Aspect
@Component
public class testAspect {

	private static final Logger logger = LoggerFactory.getLogger(testAspect.class);
	/**
	 * @Pointcut定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。
	 */
    //定义切点
	@Pointcut("@annotation(com.controller.test.TestAnnotation)")
	public void testAspect() {}

	/**
	 * 前置通知处理
	 * @param joinPoint,在Spring AOP中一个连接点代表一个方法的执行
	 * 通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。
	 * 通知有各种类型,其中包括"around"、"before”和"after"等通知。
	 * 许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链
	 */
	/** 通知类型
     * 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)
     *(返回后通知(@AfterReturning):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
     * 抛出异常后通知(@AfterThrowing):方法抛出异常退出时执行的通知
     * 后通知(@After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)
     * 环绕通知(@Around):包围一个连接点(join point)的通知,如方法调用。
     * 这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,
     * 它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
     * */
	@Before("testAspect()")
	public void doBefore(JoinPoint joinPoint) {
		try {
			System.out.println("=====start=====");
			System.out.println("class.method:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
			System.out.println("value:" + getMethodValue(joinPoint));
			System.out.println("=====end=====");
		} catch (Exception e) {
			// 记录本地异常日志
			logger.error("=======exception======");
			logger.error("exception", e.getMessage());
		}
	}
/**
 * 获取方法注解的值
 * @param joinPoint
 * @return
 * @throws Exception
 */
	@SuppressWarnings("rawtypes")
	public static String getMethodValue(JoinPoint joinPoint) throws Exception {
		//根据连接点获取class
		String targetName = joinPoint.getTarget().getClass().getName();
		//根据连接点获取method
		String methodName = joinPoint.getSignature().getName();
		//根据连接点获取args
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String value = "";
		//获取注解连接点的值
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					value = method.getAnnotation(TestAnnotation.class).value();
					break;
				}
			}
		}
		return value;
	}
}

3.在Controller中使用注解
@Controller
@RequestMapping(value = "/test")
public class testController extends BaseController {
	Log log = LogFactory.getLog(testController.class);
	@RequestMapping(value = "/charts")
	@TestAnnotation("测试fusioncharts")
	public String testFusionCharts(HttpServletRequest request,HttpServletResponse response,Model model) {
		log.info("====Start-charts");
		String strXML="<graph caption='Monthly Unit Sales' xAxisName='Month'" +
				" yAxisName='Units' decimalPrecision='0' formatNumberScale='0'>"+
	    "<set name='Jan' value='462' color='AFD8F8' />"+
	    "<set name='Feb' value='857' color='F6BD0F' />"+
	    "<set name='Mar' value='671' color='8BBA00' />"+
	    "<set name='Apr' value='494' color='FF8E46' />"+
	    "<set name='May' value='761' color='008E8E' />"+
	    "<set name='Jun' value='960' color='D64646' />"+
	    "<set name='Jul' value='629' color='8E468E' />"+
	    "<set name='Aug' value='622' color='588526' />"+
	    "<set name='Sep' value='376' color='B3AA00' />"+
	    "<set name='Oct' value='494' color='008ED6' />"+
	    "<set name='Nov' value='761' color='9D080D' />"+
	    "<set name='Dec' value='960' color='A186BE' />"+
	"</graph>";
		model.addAttribute("strXML", strXML);
		log.info("====End-charts");
		return "test/charts";
	}
}

4.启动aop注解
<!--通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller 必须放在ApplicationContext-mvc.xml文件中-->
<aop:aspectj-autoproxy proxy-target-class="true" />
5.启动web访问host:8080/webName/test/charts,控制台输出:
=====start=====
class.method:com.fh.controller.test.testController.testFusionCharts()
value:测试fusioncharts
=====end=====
2016-05-31 16:02:53 -65343 [http-bio-80-exec-5] INFO    - ====Start-charts
2016-05-31 16:02:53 -65346 [http-bio-80-exec-5] INFO    - ====End-charts

你可能感兴趣的:(java,spring,AOP,框架,Web)