Ich bin mit einer Situation konfrontiert, wo die Bohnen, die ich erstellt habe, nicht zugänglich sind, was mich fragt, wo und wann sie sind?Einschränkungen wo oder wann Bohnen sind zugänglich
Ich habe zwei Bohnen gemacht, ein Bereich singleton
und anderen Bereich request
. Ich habe sichergestellt, dass sie korrekt implementiert sind, indem Sie sie in einer RestController
Klasse automatisch ablaufen lassen. Und sie sind zweifellos dort bevölkert.
Jetzt habe ich eine Autorisierungs-Checker-Klasse geschrieben, die PreInvocationAuthorizationAdvice
erweitert. Als Berechtigungsklasse muss ich auf die aktuellen Benutzerinformationen zugreifen können. Also habe ich die Bean des aktuellen Benutzers mit dieser Klasse autowired, das ist die request
Scoped Bean. Außerdem benötige ich eine angepasste ACL-Engine, die in einer Autowirke in einer singleton
Weise betrieben wird. Aber wenn ich den Punkt erreiche, an dem ich diese beiden Eigenschaften verwenden muss, sind sie beide null
!
Was sind die Einschränkungen wo und wann ich erwarten kann, dass eine Bean erreichbar ist?
BTW, meine @Configuration
Klasse wird auch von @ComponentScan({"my.base.package"})
kommentiert, die ein Elternpaket meiner designierten Klasse einschließlich der @Autowired
Eigenschaft ist.
[UPDATE]
Ich glaube, ich gefunden, was das Problem ist, aber noch mit der Lösung, die ich bin zu kämpfen.
Die Klasse mit den Eigenschaften @Autowired
wird als Bean selbst instanziiert. Ich denke, dass diese späte Bohne vor den anderen Bohnen instanziiert wird, von denen sie abhängig ist und als Ergebnis sind sie noch nicht verfügbar. Kann ich die Reihenfolge der instanziierten Bohnen angeben?
[PS]
Wer diese Frage als "off-topic, weil: Diese Frage nicht über die Programmierung zu sein scheint" markiert so lustig :)
[UPDATE]
Nur ein Beispiel, wenn @Autowired
Eigenschaft ist null.
Das sind meine Konfigurationsklassen:
@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);
}
}
}
Und schließlich, wo ich das Problem:
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!
}
}
Könnten Sie in der Lage sein, ein Codebeispiel zu teilen, das das Problem reproduziert? – CodeChimp
Wenn Sie '@ Autowired' verwendet haben, können sie nicht null sein, wenn sie null wären, würden Sie eine Ausnahme erhalten. Zeigen Sie die Konfiguration an, die Sie verwenden. Wenn Sie Spring Boot verwenden, können Sie einfach 'SecurityContextHolder.getContext(). GetAuthentication()' verwenden, um den aktuellen Benutzer zu erhalten. –
@ M.Deinum Sie können null sein, es ist nur eine Frage der Zeit. Irgendwann sind sie null, bevor sie es nicht sind. Ich denke, ich greife auf sie zu, bevor sie instanziiert werden. Ich habe den Stiel aktualisiert. – Mehran