私が作成したBeanにアクセスできない状況に直面しています。Beansのアクセス可能な場所と時間に関する制限
私は2つの豆を作りました.1つはスコープsingleton
と他のスコープはrequest
です。私は彼らがRestController
クラスでautowiringすることによって正しく実装されていることを確認しました。そして、彼らは人口が多い、間違いなくそこにあります。
今度はPreInvocationAuthorizationAdvice
に拡張された認可チェッカークラスを作成しました。認証クラスであるため、私は現在のユーザーの情報にアクセスする必要があります。だから私は現在のユーザーのBeanをこのクラスにautowired、これはrequest
スコープBeanです。また、私はsingleton
の方法でautowiredされているカスタマイズされたACLエンジンが必要です。しかし、私はこれらの2つのプロパティを使用する必要がある時点に達すると、両方ともnull
です!
だから、どこでいつ私がBeanにアクセスできると予想できるの?
私の@Configuration
クラスには、@Autowired
プロパティを含む私の指定されたクラスの親パッケージである@ComponentScan({"my.base.package"})
によっても注釈が付けられます。
[UPDATE]
私は問題が何であるかを見つけたと思うが、まだ私は解決策に苦しんでいます。
プロパティが@Autowired
のクラスは、Bean自体としてインスタンス化されています。私は、この後期のBeanは、それが依存している他のBeanの前にインスタンス化されていると考えています。その結果、まだ利用できません。とにかくインスタンス化されているBeanの順序を指定できますか?
[PS] としてこの質問にフラグを立て
誰でも: "ので、オフトピックこの質問は、プログラミングについてではありませんが、" とても面白いです:)
[UPDATE]
@Autowired
プロパティがnullの場合の例です。私は問題に直面
@Configuration
@PropertySource("/config.properties")
@ComponentScan({"my.package"})
public class AppConfig implements ApplicationContextAware
{
private ApplicationContext appContext;
@Autowired
private Environment env;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException
{
this.appContext = applicationContext;
}
@Bean
public RedissonClient getRedisson()
{
//Code ommited: returning a redisson connection.
}
}
@Configuration
@ComponentScan({"my.pacakge"})
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration
{
@Bean
public AclEngine getAclEngine()
{
return new AclEngine();
}
@Autowired
private RedissonClient redisson;
@Bean
@Scope(value = "request")
public User getCurrentUser()
{
//Code ommited: retrieving the user from Redisson and returning it.
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception
{
auth.authenticationProvider(authenticator());
}
@Bean
public AuthenticationProvider authenticator()
{
return new AclAuthenticationProvider();
}
@Bean
HttpSessionSecurityContextRepository getHttpSessionSecurityContextRepository()
{
HttpSessionSecurityContextRepository x = new HttpSessionSecurityContextRepository();
x.setAllowSessionCreation(false);
return x;
}
@Bean
SecurityContextPersistenceFilter getSecurityContextPersistenceFilter()
{
return new SecurityContextPersistenceFilter(getHttpSessionSecurityContextRepository());
}
@Override
protected AccessDecisionManager accessDecisionManager()
{
try {
AffirmativeBased ab = (AffirmativeBased) super.accessDecisionManager();
List<AccessDecisionVoter<? extends Object>> advs = ab.getDecisionVoters();
ResourceBasedPreInvocationAdvice expressionAdvice = new ResourceBasedPreInvocationAdvice();
List<AccessDecisionVoter<? extends Object>> toBeRemoved = new ArrayList<>();
for (AccessDecisionVoter<? extends Object> adv : advs) {
if (adv instanceof PreInvocationAuthorizationAdviceVoter) {
toBeRemoved.add(adv);
}
}
for (AccessDecisionVoter<? extends Object> adv : toBeRemoved) {
advs.remove(adv);
}
advs.add(new PreInvocationAuthorizationAdviceVoter(expressionAdvice));
return ab;
}
catch (ClassCastException ex) {
ArrayList decisionVoters = new ArrayList();
ResourceBasedPreInvocationAdvice expressionAdvice = new ResourceBasedPreInvocationAdvice();
decisionVoters.add(new PreInvocationAuthorizationAdviceVoter(expressionAdvice));
return new AffirmativeBased(decisionVoters);
}
}
public class AclAuthenticationProvider implements AuthenticationProvider
{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
return null;
}
@Override
public boolean supports(Class<?> authentication)
{
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
public class SessionInitializer extends AbstractHttpSessionApplicationInitializer
{
public SessionInitializer()
{
super(SecurityConfig.class);
}
}
}
そして最後に:
これらは私の設定クラスです
public class ResourceBasedPreInvocationAdvice implements PreInvocationAuthorizationAdvice
{
@Autowired
private User currentUser;
@Autowired
private AclEngine aclEngine;
@Override
public boolean before(Authentication authentication, MethodInvocation methodInvocation, PreInvocationAttribute preInvocationAttribute)
{
//Where I want to access currentUser and aclEngine but they are null.
//I can trace the code to this point without any Exception thrown!
}
}
問題を再現するコード例をいくつか共有できますか? – CodeChimp
'@ Autowired'を使用している場合は、nullにすることはできません。ヌルになると例外が発生します。使用している構成を表示します。また、Spring起動時に 'SecurityContextHolder.getContext()。getAuthentication()'を実行するだけで、現在のユーザを取得することができます。 –
@ M.Deinumそれらはnullでもかまいません。時間の問題です。ある時点では、それらはそうでない前にはヌルです。私はインスタンス化される前にそれらにアクセスしていると思います。私は茎を更新しました。 – Mehran