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);
}
}
Tomaszが提案したAopContext.currentProxy()
は機能します。プロキシされたクラスの外部で機能するより一般的な解決策は、オブジェクトを_org.springframework.aop.framework.Advised
_にキャストし、.getTargetSource().getTarget()
を取得することです。
前者(プロキシされたオブジェクトから実際のオブジェクトを取得する)は、実際には必要ないものです。一方、ターゲットプロキシを取得することは、機能を追加するために既存のBeanを検査するユーティリティクラスで役立つ場合があります。
Beanポストプロセッサを使用して、ターゲットBeanのプロキシへの参照を設定できます。 Spring固有のものをBeanから単一のクラスに移動します。
後処理
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) ;
}
次に、プロキシを介して自分自身を呼び出す必要がある各BeanにsetProxy
を実装します。
public class MyBean implements SelfReferencingBean {
MyBean proxy;
@Override
public void setProxy(Object proxy) {
this.proxy = (MyBean) proxy;
}
}
メソッドを直接呼び出すときにproxy
をBeanの型にキャストしてもかまわない場合は、この最後のコードをBean基本クラスに入れることができます。 Method.invoke
を通過しているので、キャストすら必要ありません。
少しの作業で、これを@Autowired
の注釈プロセッサに変換できると思います。考えてみると、@Autowired
自体を使用して自己参照を追加しようとしたかどうかは思い出せません。
public class MyBean implements SelfReferencingBean {
@Autowired MyBean proxy;
}