(loop (print (eval (read))))

;;닭집을 차리기 위한 여정

Spring aop example

guice가 참 좋은데.. 정말 좋은데

이런 어노테이션이 있다고 하자.

1
2
3
4
5
6
7
8
9
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorized {
Type to();
enum Type {
PUBLIC, ADMIN
}
}

이런 쥬스 모듈에 의해 바인딩되고,

1
2
3
4
5
6
7
8
public class AuthorizeModule extends AbstractModule {
@Override
protected void configure() {
AuthorizeInterceptor authorizeInterceptor = new AuthorizeInterceptor();
requestInjection(authorizeInterceptor);
bindInterceptor(Matchers.inSubpackage("com.foo.example"), Matchers.any(), authorizeInterceptor);
}
}

이런 인터셉터를 호출한다 ㅎㅎ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AuthorizeInterceptor implements MethodInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AuthorizeInterceptor.class);
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Authorized authorized = invocation.getMethod().getAnnotation(Authorized.class);
if(authorized != null && authorized.to() == Authorized.Type.PUBLIC)
return invocation.proceed();
// FIXME: authorize! and delete below line.
logger.info("authorizing . . . ");
return invocation.proceed();
}
}

놀랍게도, 이게 다다. 아오.. 너무 좋다..

하지만 쥬스는 돈이 안 된다. 따라서 이걸 스프링으로 해 보자.

스프링에서의 aop

먼저 advice 를 만든다.

1
2
3
4
5
6
7
8
public class FooAdvice implements MethodBeforeAdvice {
private static final Logger LOGGER = LoggerFactory.getLogger(FooAdvice.class);
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
LOGGER.warn("Capitalism, ho!");
}
}

그 다음 pointcut 을 만든다.

1
2
3
4
5
6
7
8
9
@Bean
Pointcut pointcut(){
return new ComposablePointcut().union(
clazz -> clazz.getPackage().getName().equals("com.foo.example.controller") &&
clazz.getAnnotation(Controller.class) != null
).intersection(
new AnnotationMethodMatcher(FooAnnotation.class)
);
}

위에서 ComposablePointcut 이 쥬스에서 하던 바인딩과 유사하여 꽤나 쓸만하다. jdk8 과 만나 드디어 사람이 읽을 수 있는 표현이 되었다!!

다음 pointcut advisor 를 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Bean
PointcutAdvisor pointcutAdvisor(){
return new DefaultPointcutAdvisor(pointcut(),advice());
}
```
위에서 만든 `pointcut` , `adivce` , `pointcut advisor` 는 반드시 다음 `DefaultAdvisorAutoProxyCreator` 를 통해야만 프록시가 생성된다.
```java
@Bean
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}

이렇게 하면 쥬스로 했던거랑 딱히 다를것도 없다. 우왕!