Получить прокси AOP от самого объекта
Возможно ли получить прокси данного объекта в Spring? Мне нужно вызвать функцию подкласса. Но, очевидно, когда я делаю прямой звонок, аспекты не применяются. Вот пример:
public class Parent {
public doSomething() {
Parent proxyOfMe = Spring.getProxyOfMe(this); // (please)
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
public class Child extends Parent {
@Secured("president")
public void sayHello() {
System.out.println("Hello Mr. President");
}
}
Я нашел способ достичь этого. Это работает, но я думаю, не очень элегантно
public class Parent implements BeanNameAware {
@Autowired private ApplicationContext applicationContext;
private String beanName; // Getter
public doSomething() {
Parent proxyOfMe = applicationContext.getBean(beanName, Parent.class);
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
3 ответа
AopContext.currentProxy()
как предложено Томашем будет работать. Более общее решение, которое будет работать за пределами класса прокси, - привести объект к org.springframework.aop.framework.Advised
и получить .getTargetSource().getTarget()
Первый (получение реального объекта от объекта прокси) - это то, что вам не нужно. С другой стороны, получение целевого прокси может быть полезно в некотором служебном классе, который проверяет существующие bean-компоненты для добавления некоторой функции.
Вы можете использовать постпроцессор бина, чтобы установить ссылку на прокси на целевом бине. Он перемещает спецификацию Spring из ваших бинов в один класс.
Пост-процессор
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class SelfReferencingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof SelfReferencingBean) {
((SelfReferencingBean) bean).setProxy(bean);
}
return bean;
}
}
контекст
Зарегистрировать постпроцессор в applicationContext.xml
,
<bean id="srbpp" class="SelfReferencingBeanPostProcessor"/>
Фасоль
Каждый бин должен реализовывать SelfReferencingBean
сообщить постпроцессору, что ему нужна ссылка на прокси.
public interface SelfReferencingBean {
void setProxy(Object proxy) ;
}
Сейчас реализуем setProxy
в каждом бине, который должен вызывать себя через свой прокси.
public class MyBean implements SelfReferencingBean {
MyBean proxy;
@Override
public void setProxy(Object proxy) {
this.proxy = (MyBean) proxy;
}
}
Вы можете поместить этот последний кусочек кода в базовый класс бина, если не возражаете proxy
к типу бина при вызове методов непосредственно на нем. Так как вы проходите через Method.invoke
вам даже не понадобится актерский состав.
Немного потрудившись поспорить, что это можно преобразовать в процессор аннотаций а-ля @Autowired
, Если подумать, я не помню, пытался ли я добавить ссылку на себя, используя @Autowired
сам.
public class MyBean implements SelfReferencingBean {
@Autowired MyBean proxy;
}