Java Springbean中的Firebase初始化未触发onDataChange
我正在使用firebase admin sdk for java。当我创建java控制台应用程序时,下面的代码按预期工作。但是,如果我在springboot应用程序的bean初始化中放入相同的代码,那么它永远不会进入onDataChange EventHandler中 我甚至试着在末尾放置一个具有足够延迟的Thread.sleep(),以检查这是否是因为初始化bean的线程正在退出而发生的。然而,这没有帮助 在SpringBean中这样做的正确方法是什么Java Springbean中的Firebase初始化未触发onDataChange,java,firebase-realtime-database,firebase-admin,Java,Firebase Realtime Database,Firebase Admin,我正在使用firebase admin sdk for java。当我创建java控制台应用程序时,下面的代码按预期工作。但是,如果我在springboot应用程序的bean初始化中放入相同的代码,那么它永远不会进入onDataChange EventHandler中 我甚至试着在末尾放置一个具有足够延迟的Thread.sleep(),以检查这是否是因为初始化bean的线程正在退出而发生的。然而,这没有帮助 在SpringBean中这样做的正确方法是什么 import com.google.au
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.database.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Repository;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
@Repository
@EnableAsync
public class MyBean {
FirebaseDatabase db;
public MyBean() {
try {
File file = new File(
getClass().getClassLoader().getResource("myKey.json").getFile()
);
FileInputStream fis = new FileInputStream(file);
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(fis))
.setDatabaseUrl("https://myUrl/")
.build();
FirebaseApp.initializeApp(options);
db = FirebaseDatabase.getInstance();
DatabaseReference ref = db
.getReference("/a/b/c");
ref.addValueEventListener(new ValueEventListener() {
//The code execution never comes in here
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("dataSnapshot.exists() :"+ dataSnapshot.exists());
}
public void onCancelled(DatabaseError error) {
System.out.print("Error: " + error.getMessage());
}
});
// Thread.sleep(10000);
} catch (Exception ex) {
String err=ex.getMessage();
}
}
`
查看
FirebaseReference.getReference()方法的源代码:
public DatabaseReference getReference() {
return new DatabaseReference(ensureRepo(), Path.getEmptyPath());
}
每次调用时,它都会创建一个新的数据库引用。您现在的做法是将ValueEventListener
添加到DatabaseReference
中,因为您没有以某种方式将其从该方法中传递出去,因此它将被垃圾收集
我建议将您的数据库引用
对象声明为@配置
类中的bean:
@Configuration
public class FirebaseConfig {
// This is just the ApplicationContext, injected through abstraction
private final ResourceLoader resourceLoader;
@Autowired // Constructor injection, recommended above field and setter injections
public FirebaseConfig(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Bean
public FirebaseDatabase firebaseDatabase() throws IOException {
Resource resource = resourceLoader.getResource("classpath:myKey.json");
InputStream inputStream = resource.getInputStream();
FirebaseOptions firebaseOptions = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(inputStream))
.setDatabaseUrl("url")
.build();
FirebaseApp.initializeApp(firebaseOptions);
return FirebaseDatabase.getInstance();
}
@Bean
public DatabaseReference databaseReference(FirebaseDatabase firebaseDatabase) {
DatabaseReference ref = firebaseDatabase.getReference();
ref.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("dataSnapshot.exists() :" + dataSnapshot.exists());
}
public void onCancelled(DatabaseError error) {
System.out.print("Error: " + error.getMessage());
}
});
return ref;
}
}
现在,在Spring应用程序中,您应该自动连接这个数据库引用bean
更优雅的解决方案是将ValueEventListener
分离到它自己的bean中,并将其自动连接到DatabaseReference
bean方法中:
@Bean
public DatabaseReference databaseReference(
FirebaseDatabase firebaseDatabase,
// List injection will be populated with all ValueEventListener beans in the ApplicationContext
List<ValueEventListener> valueEventListeners
) {
DatabaseReference ref = firebaseDatabase.getReference();
valueEventListeners.forEach(ref::addValueEventListener);
return ref;
}
您可能希望启用调试日志并查看SDK中发生了什么。很可能它遇到了错误,并以静默方式失败。您能否尝试将@Import(MyBean.class)添加到@springbootplication
所在的main应用程序`类中?这只是为了确保MyBean的组件扫描正确。
@Component
public class SystemOutListener implements ValueEventListener {
@Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println("dataSnapshot.exists() :"+ snapshot.exists());
}
@Override
public void onCancelled(DatabaseError error) {
System.out.print("Error: " + error.getMessage());
}
}