SPRING-SOURCE.RU | |
|
|
На изображении показано, что аспект логирования применен к главному приложению при помощи pointcuts. Pointcut в АОП описывает, где и как код аспекта должен быть вставлен в целовой код. Изображение показывает как Spring AOP смотрит pointcuts и применяет аспекты в целевом коде в нескольких joint points.
В этой части, вы сможете попробовать Spring AOP, применив аспект логирования к уже существующему приложению — Calculation.
Код для аспекта:
package com.wrox.begspring.aspects; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class LoggingAspect { @Before("execution(* com.wrox.begspring.Operation.*(..))") public void logMethodExecution(JoinPoint jp) { System.out.println("AOP logging -> " + jp.toShortString() ); } }
Аспект логирования, который будет применяться выделен жирным цветом. Запомните, что никто не знает об этом коде аспекта, который ссылается на CalculateSpring код — цель к которой он применяется. В действительности, этот аспект может быть отредактирован независимо от CalculateSpring кода.
Этот код выводит сообщение, похожее на следующее, всякий раз, когда вызывается метод Operation в интерфейсе. Вызов происходит из CalculateSpring кода. Результат вызова:
AOP logging -> execution(getOpsName)
Обратите внимание, что запуск двух методов getOpsName() и operate() из интерфейса, вызывает логирование. Еще, реализация интерфейсов - таких как OpAdd и OpMultiply - не логируются вовсе.
Главный код для CalculateSpring переименован в CalculateSpringAOP, и показан здесь:
package com.wrox.begspring; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class CalculateSpringAOP { private Operation ops; private ResultWriter wtr; public void setOps(Operation ops) { this.ops = ops; } public void setWriter(ResultWriter writer) { wtr = writer; } public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml"); BeanFactory factory = (BeanFactory) context; CalculateSpringAOP calc = (CalculateSpringAOP) factory.getBean("opsbean"); calc.execute(args); } public void execute(String [] args) { long op1 = Long.parseLong(args[0]); long op2 = Long.parseLong(args[1]); wtr.showResult("The result of " + op1 + ops.getOpsName() + op2 + " is " + ops.operate(op1, op2) + "!"); } }
Обратите внимание, что этот главный код вообще не модифицируется. Аспект примененный через SpringAOP не требует внесения перемен в тело целевого кода.
Как и другие Spring техники, АОП связывает через конфигурационный файл (описание контекста). Если посмотреть в beans.xml файл, можно увидеть, как именно применяется аспект.
<?xml version=”1.0” encoding=”UTF-8”?> <beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:aop=”http://www.springframework.org/schema/aop” xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd”> <bean id=”screen” class=”com.wrox.begspring.ScreenWriter” /> <bean id=”multiply” class=”com.wrox.begspring.OpMultiply” /> <bean id=”opsbean” class=”com.wrox.begspring.CalculateSpringAOP” autowire=”byType”/> <aop:aspectj-autoproxy/> <bean id=”logaspect” class=”com.wrox.begspring.aspects.LoggingAspect”/> </beans>
Spring контейнер обрабатывает элемент <aop:aspectj-autoproxy> и автоматически создает динамический прокси, необходимый для АОП когда он связывает бины вместе. Прокси автоматически добавляются Spring-ом к CaculateSpringAOP классу.
В этом случае, Spring 2 использует AspectJ pointcut язык (будет описываться в следующих секциях).
Java аннотации используются для того, чтобы определить pointcut, соответственно указывая, где будет применен аспект.
package com.wrox.begspring.aspects; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class LoggingAspect { @Before(“execution(* com.wrox.begspring.Operation.*(..))”) public void logMethodExecution(JoinPoint jp) { System.out.println(“AOP logging -> “ + jp.toShortString() ); } }
@Aspect аннотация выделяет этот класс как аспект. @Before аннотация определяет текущую pointcut. Это выражение говорит, Примени этот аспект перед тем, как ты вызовешь любой метод типа com.wrox.begspring.Operation.
Com.wrox.begspring.Operation - это интерфейс и результат в аспекте будет всегда выводиться перед запуском метода c любой реализацией этого интерфейса.
Аргумент у метода logMethodExecution() - это join point. В нашем случае мы вызываем toShortString(), а вообще у join point существует немного больше методов. Здесь описывать мы их не станем.
Aspect - это java класс и мы можем определять их сколько угодно. Теперь мы можем соединять аспекты логирования, которые разделены между собой, можем гибко применять их к большому количеству кода через манипулирование pointcut выражениями. Это суть того, как АОП может оказаться полезным в повседневной работе программиста.
Copyright © 2024 |