1
2
3
4
5
6
7
|
@RequestMapping (method = RequestMethod.GET) public String showEmployees(Model model) { List<Employee> employees = employeeDao.list(); model.addAttribute( 'employees' , employees); return 'employees/list' ; } |
он сделал следующий код:
01
02
03
04
05
06
07
08
09
10
|
@RequestMapping (method = RequestMethod.GET) public String showEmployees(Model model) { LOGGER.log( 'Invoking method showEmployees' ); List<Employee> employees = employeeDao.list(); model.addAttribute( 'employees' , employees); LOGGER.log( 'Returning from method showEmployees' ); return 'employees/list' ; } |
Что не так с этим кодом? Что ж:
Например, какова ответственность метода showEmployees? Это вызов службы, привлечение сотрудников и их моделирование. Ведение журнала — это не ответственность, так зачем смешивать эти проблемы?
Если бы упомянутый мной инженер знал об аспектно-ориентированном программировании, он бы сэкономил много времени и сделал код лучше и читабельнее. Spring поддерживает то, что называется «Аспекты», которые созданы именно для таких задач. Аспекты позволяют нам определять общую функциональность в одном месте. Прежде чем писать какой-либо код, необходимо разобраться в терминологии. Эта терминология довольно обширна, и я не собираюсь ее здесь писать, но я призываю вас прочитать официальную справочную страницу Spring на АОП, если вы хотите узнать больше. Вы должны по крайней мере понять, что такое Advice, Join Point, Pointcut, Aspect и Weaving.
Хорошо, давайте добавим Aspect для регистрации методов контроллера, именно то, что должен был сделать инженер из истории в начале.
Сначала мы должны добавить зависимости в pom.xml в библиотеке AspectJ:
01
02
03
04
05
06
07
08
09
10
|
< dependency > < groupId >org.aspectj</ groupId > < artifactId >aspectjrt</ artifactId > < version >1.6.11</ version > </ dependency > < dependency > < groupId >org.aspectj</ groupId > < artifactId >aspectjtools</ artifactId > < version >1.6.11</ version > </ dependency > |
Также проверьте, есть ли у вас зависимость от Spring AOP (но если вы следуете этому руководству с самого начала, оно у вас уже есть):
1
2
3
4
5
|
< dependency > < groupId >org.springframework</ groupId > < artifactId >spring-aop</ artifactId > < version >3.1.0.RELEASE</ version > </ dependency > |
Теперь давайте напишем код Аспекта. Создать пакет org.timesheet. аспекты и добавить класс ControllerLoggingAspect:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package org.timesheet.aspects; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import java.util.Arrays; /** * Will log every invokation of @RequestMapping annotated methods * in @Controller annotated beans. */ @Aspect public class ControllerLoggingAspect { @Pointcut ( 'within(@org.springframework.stereotype.Controller *)' ) public void controller() {} @Pointcut ( 'execution(* *(..))' ) public void methodPointcut() {} @Pointcut ( 'within(@org.springframework.web.bind.annotation.RequestMapping *)' ) public void requestMapping() {} @Before ( 'controller() && methodPointcut() && requestMapping()' ) public void aroundControllerMethod(JoinPoint joinPoint) throws Throwable { System.out.println( 'Invoked: ' + niceName(joinPoint)); } @AfterReturning ( 'controller() && methodPointcut() && requestMapping()' ) public void afterControllerMethod(JoinPoint joinPoint) { System.out.println( 'Finished: ' + niceName(joinPoint)); } private String niceName(JoinPoint joinPoint) { return joinPoint.getTarget().getClass() + '#' + joinPoint.getSignature().getName() + '\n\targs:' + Arrays.toString(joinPoint.getArgs()); } } |
Этот код говорит, что @Before и @AfterReturning из метода контроллера мы будем регистрировать информацию о его вызове (имя и аргументы). Этот совет выполняется, когда все три pointcut совпадают. controller () pointcut помечает совпадающую точку соединения (которая соответствует стереотипу Controller), в которой должен быть создан совет. methodPointcut () отмечает, что мы имеем дело с вызовом метода, а requestMapping () pointcut отмечает методы, аннотированные @RequestMapping.
Чтобы это работало, мы добавим конфигурационный файл Spring aop.xml в src / main / resources:
01
02
03
04
05
06
07
08
09
10
11
12
|
<? xml version = '1.0' encoding = 'UTF-8' ?> 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd' > <!-- AOP support --> < bean id = 'controllerAspect' class = 'org.timesheet.aspects.ControllerLoggingAspect' /> < aop:aspectj-autoproxy > < aop:include name = 'controllerAspect' /> </ aop:aspectj-autoproxy > </ beans > |
И затем мы импортируем его в конфигурационный файл timesheet-servlet.xml Spring:
1
|
< import resource = 'classpath:aop.xml' /> |
Это была последняя часть урока. Я надеюсь, что теперь вы лучше понимаете, что такое Spring и как он помогает решать ваши проблемы. Помните, что мы рассмотрели только маленький кусочек Spring в этом уроке. Еще многое предстоит изучить!
Ссылка: Часть 6. Добавление поддержки AOP от нашего партнера JCG Михала Вртиака в блоге vrtoonjava .