Ответ 1
Этот взлом крайне неудобен, пожалуйста, подумайте о том, как реорганизовать ваш код или использовать плетение AspectJ. Вы можете чувствовать себя предупрежденным, вот решение
AopContext.currentProxy()
Можно ли получить прокси-объект данного объекта в 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);
}
}
Этот взлом крайне неудобен, пожалуйста, подумайте о том, как реорганизовать ваш код или использовать плетение AspectJ. Вы можете чувствовать себя предупрежденным, вот решение
AopContext.currentProxy()
AopContext.currentProxy()
, как предложил Томаш. Более общее решение, которое будет работать вне класса прокси, - это передать объект в org.springframework.aop.framework.Advised
и получить .getTargetSource().getTarget()
Первое (получение реального объекта из прокси-объекта) - это то, что вам действительно не нужно. С другой стороны, получение целевого прокси-сервера может быть полезным в некоторых классах, которые проверяют существующие beans, чтобы добавить некоторые функции.
Вы можете использовать постпроцессор bean, чтобы установить ссылку на прокси-сервер в целевом bean. Он перемещает Spring -специфики из вашего beans в один класс.
постпроцессор
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"/>
Beans
Каждый bean должен реализовать SelfReferencingBean
, чтобы сообщить постпроцессору, что ему нужна ссылка на прокси.
public interface SelfReferencingBean {
void setProxy(Object proxy) ;
}
Теперь реализуем setProxy
в каждом bean, который должен вызывать себя через свой прокси.
public class MyBean implements SelfReferencingBean {
MyBean proxy;
@Override
public void setProxy(Object proxy) {
this.proxy = (MyBean) proxy;
}
}
Вы можете поместить этот последний бит кода в базовый класс bean, если вы не возражаете против ввода proxy
в bean типа при вызове методов непосредственно на нем. Поскольку вы проходите через Method.invoke
, вам даже не понадобится бросок.
С небольшой работой, я уверен, это можно было бы преобразовать в обработчик аннотации a la @Autowired
. Подумайте об этом, я не помню, даже если я попытался добавить самооценку, используя @Autowired
.
public class MyBean implements SelfReferencingBean {
@Autowired MyBean proxy;
}