|
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. */@Aspectpublic 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 .