Spring bean生命周期中有许多初始化选项.
init-method,PostConstruct注释,afterPropertiesSet,Bean 后初始化甚至是类构造函数.所有这些都可以用于初始化bean.
我很困惑何时使用其中一个.此外,有没有我们可能需要在一个Bean中使用所有这些选项?如果是,请举例说明.
真的很期待得到一些很好的答案.
在我的视图作用域的managedBean中,我需要用DB中的数据填充列表.我这样做是通过构造函数的直接调用,如下所示:
public MyClass(){
list=populateFromDb();
}
Run Code Online (Sandbox Code Playgroud)
但是这个方法可以在@PostConstruct注释方法中调用,如:
public MyClass(){
}
@PostConstruct
populateFromDb(){...}
Run Code Online (Sandbox Code Playgroud)
这有什么区别?
我有一个关于POJO中List的初始化的问题,因为它遵循下一个代码:
public class Person {
//other fields...
private List<String> friends=new ArrayList<>();
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
}
Run Code Online (Sandbox Code Playgroud)
或者它是这样的更好,并在其他类中具有初始化(例如Bean(JSF))
public class Person {
//other fields...
private List<String> friends;
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是什么方法更好?
这很疯狂......一直使用Spring一段时间但是找不到像所有依赖项被注入后调用的"init-method"之类的东西.
我看到BeanPostProcessor的东西,但我正在寻找一些轻量级和非侵入性的东西,不会将我的bean耦合到Spring.像init方法一样!
我希望在Spring Context中执行一些设置方法.
我目前有以下代码,但它不起作用,因为我说它们是beans没有返回类型.
@Configuration
@Component
public class MyServerContext {
...
// Works
@Bean
public UserData userData() {
UserData userData = new AWSUserDataFetcher(urlUtil()).fetchUserData();
return userData;
}
// Doesn't work
@Bean
public void setupKeyTrustStores() {
// Setup TrustStore & KeyStore
System.setProperty(SYS_TRUST_STORE, userData().get(TRUST_STORE_PATH));
System.setProperty(SYS_TRUST_STORE_PASSWORD, userData().get(TRUST_STORE_PASSWORD));
System.setProperty(SYS_KEY_STORE, userData().get(KEY_STORE_PATH));
System.setProperty(SYS_KEY_STORE_PASSWORD, userData().get(KEY_STORE_PASSWORD));
// Prevents handshake alert: unrecognized_name
System.setProperty(ENABLE_SNI_EXTENSION, "false");
}
...
}
Run Code Online (Sandbox Code Playgroud)
如何在@Configuration没有@Bean注释的情况下自动运行此方法?
在@Service类中有几个用@Value注释的字段.这些字段未正确填充并且为空.也许我忽略了一些事情,我已经粘贴了下面的相关代码块.尝试了具有相同结果的替代选项env.getProperty().
输出中以下属性的值为null.
package com.project.service.impl;
import org.springframework.beans.factory.annotation.Value
@Service("aService")
@PropertySource(value="classpath:app.properties")
public class ServiceImpl implements Service{
private Environment environment;
@Value("${list.size}")
private Integer list1;
@Value("${list2.size}")
private Integer list2Size;
@Autowired
public ServiceImpl(StringRedisTemplate stringTemplate){
this.stringTemplate = stringTemplate;
logger.info("TESTING 123: "+list1);
}
// ...
}
@EnableWebMvc
@ComponentScan(basePackages = {"com.project.service","..."})
@Configuration
public class ServletConfig extends WebMvcConfigurerAdapter {
// ...
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[] {
new ClassPathResource("app.properties")
};
propertyPlaceholderConfigurer.setLocations(resources);
propertyPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
return propertyPlaceholderConfigurer;
}
}
Run Code Online (Sandbox Code Playgroud) 让我们举一个基本的例子.在servlet应用程序中,我将拥有这些类:
Register(User).会打电话给DAO.WEB-INF\JSPs\registration.jsp哪个会处理视图.所有这些对我来说都很有意义,并且明确区分了这些问题.
我已经尝试过围绕JSF/Facelets的思维方式.我已经在SO和其他地方经历了许多优秀的资源,但是没有任何地方可以解决这个简单的问题 - 即dao/service/controller/view模式如何转换为JSF.
继续我的例子 - 我已经在eclipse中设置了一个JSF项目,已经将我的数据库模式转换为"entities"现在我想知道 - 我应该创建什么样的类来处理用户注册?我知道我必须为视图创建xhtml页面,但控制器在哪里?
请不要指教我- 我知道很多,其中@BalusC一个 - 我的问题不是让这个工作,而是要了解模式.我已经看到"session"包中包含"托管bean","抽象外观"模式等等,但没有任何东西可以像旧的servlet模式一样清晰.
所以 - 在DB创建的"实体"中,有一个看起来像模型的User.java类.该视图将是一个xhtml.控制器?
注意:这并不是要求这么多重复这些技术之间的差异 - 我要求将非常清晰直观的控制器/ dao /服务模式清晰地转换为JSF框架 - 或明确声明不存在这样的技术翻译.
也可以看看:
我用@ApplicationScoped注释了一个类.使用@Inject,我将这个类的实例注入到几个@RequestScopded JAX-RS服务中:
@ApplicationScoped
public class MySingleton {
MySingleton() {
System.out(this + " created.");
}
}
@RequestScoped
public class MyRS {
@Inject MySingleton mySingleton;
public void someMethod() {
// do something with mySingleton
}
}
Run Code Online (Sandbox Code Playgroud)
基本上这很好用.Howeger,至少当我在WebSphere 8.5中运行它时,MySingleton的构造函数被调用两次,导致输出像
my.package.MySingleton_$$_javassist_26@cddebf9b created.
my.package.MySingleton@e51e26d1 created.
Run Code Online (Sandbox Code Playgroud)
我打算在构造函数中做一些昂贵的初始化,显然会执行两次.
我相信其中一个构造函数调用是为实际的"worker"实例生成某种代理.但是如何避免我的初始化代码执行两次?在MySingleton的所有方法中进行延迟初始化的"解决方案"并不是很有吸引力.
我希望 Spring@DependsOn在调用@PostConstruct方法时考虑到这一点,但似乎在存在循环(自动连接)依赖项时情况并非如此。
考虑两个 bean(下面的代码),BeanB @DependsOn BeanA. 当现场BeanA#b有它@Autowired注释掉,后期构造方法的调用预期顺序:先A,然后B.但随着@Autowired在甲效果,我有B的post第一调用,那么A的post。
我知道这是一个糟糕的设计(实际上,它是非常大的@Autowired...代码库的最小演示),但我期待 Spring 完成@Autowired字段的注入,然后开始调用生命周期回调,尊重@DependsOn,但 Spring 似乎忽略了@DependsOn顺序当有圆形深度时。
Spring 版本是 4.1.5。
那么,这是我的误解或未记录的行为,还是可以将其视为Spring 错误(或者,可能是功能请求)?
@Component
class BeanA {
// @Autowired
private BeanB b;
void f() {
System.out.println(this);
}
@PostConstruct
void post() {
System.out.println("A done");
}
@Override
public String toString() {
return "Bean{" + …Run Code Online (Sandbox Code Playgroud) 我必须在我的bean上调用一个init方法作为页面加载的第一个操作,我试图#{bean.init}在我的页面的最开始调用,但我已经看到<c:if>测试是在之前执行的init().我有类似的东西
#{bean.init}
<c:if test="#{bean.conditionsCheck}">...</c:if>
Run Code Online (Sandbox Code Playgroud)
并且在conditionsCheck()之前调用该方法init(),我该如何修复它并将其init()称为第一件事?
使用Spring 3.0.x,我遇到了一个运行Bean init方法的问题,并且其中一部分提取了一些信息,然后在另一个线程中(原始init()线程等待其他线程完成)尝试根据该信息检索获取一个或多个Bean.问题是,这些其他豆类也是单身,尚未初始化.在getSingleton()方法中,DefaultSingletonBeanRegistry中有一个synchronized()块.
问题出现了,我正在尝试获取/初始化Bean,而我正在初始化Bean,所以我在init()方法中遇到主线程,另一个线程试图获取另一个单例Bean,并且被阻止,因为第一个线程有锁.
所以,我看到它的方式,我有两个选择:
1)获取Spring在完全创建单例之后运行一个方法,执行实际数据获取和处理2)提供消息传递给它将数据返回给主线程,然后在其中处理所有数据,因为它已经有显示器锁定
思考?想法?我怎样才能让#1工作?
我试图通过以下配置在spring中创建bean的映射.
<util:map id="utilBeansMap" map-class="java.util.HashMap">
<entry key="getFlightsLogger">
<bean
class="com.test.package.bean1" />
</entry>
<entry key="getOnDLogger">
<bean
class="com.test.package.bean2" />
</entry>
</util:map>
Run Code Online (Sandbox Code Playgroud)
然后使用将此Map作为资源注入另一个bean(比如UserSerice)
@Resource(name = "utilBeansMap")
private Map<String, BaseUtilBean> utilBeansMap;
Run Code Online (Sandbox Code Playgroud)
但是当我试图从这张地图中获取bean时,我得到空指针.
我看着日志.日志显示此map bean已初始化,但是当UserService开始启动时,此map bean已被销毁.
DEBUG DefaultListableBeanFactory - Creating shared instance of singleton bean 'utilBeansMap'
DEBUG DefaultListableBeanFactory - Creating instance of bean 'utilBeansMap'
DEBUG DefaultListableBeanFactory - Eagerly caching bean 'utilBeansMap' to allow for resolving potential circular references
DEBUG DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'utilBeansMap'
DEBUG DefaultListableBeanFactory - Finished creating instance of bean …Run Code Online (Sandbox Code Playgroud) spring ×7
java ×5
java-ee ×3
jsf ×3
jsf-2 ×2
spring-mvc ×2
annotations ×1
arraylist ×1
cdi ×1
constructor ×1
java-ee-6 ×1
jsp ×1
managed-bean ×1
servlets ×1
spring-boot ×1
spring-data ×1