BadPractice12 - SpotBugsExtensionForSpringFrameWork/CS5098 GitHub Wiki
Bug Name: Avoid accessing FactoryBean directly and invoking its getObject() manually, and let Spring do it for you
Avoid accessing FactoryBean directly and invoking its getObject() manually, and let Spring do it for you; if you do this manually, you are making extra work for yourself and are unnecessarily coupling your application to a specific implementation detail that could quite easily change in the future.
import org.springframework.context.support.GenericXmlApplicationContext;
import java.security.MessageDigest;
public class AccessingFactoryBeans {
public static void main(String... args) {
GenericXmlApplicationContext ctx =
new GenericXmlApplicationContext();
ctx.load("classpath:spring/app-context-xml.xml");
ctx.refresh();
ctx.getBean("shaDigest", MessageDigest.class);
MessageDigestFactoryBean factoryBean =
(MessageDigestFactoryBean) ctx.getBean("&shaDigest");
try {
MessageDigest shaDigest = factoryBean.getObject(); // Avoid this
System.out.println(shaDigest.digest("Hello world".getBytes()));
} catch (Exception ex) {
ex.printStackTrace();
}
ctx.close();
}
}
// Output: B@130f889
public class MessageDigestFactoryBean implements
FactoryBean<MessageDigest>, InitializingBean {
private String algorithmName = "MD5";
private MessageDigest messageDigest = null;
public MessageDigest getObject() throws Exception {
return messageDigest;
}
public Class<MessageDigest> getObjectType() {
return MessageDigest.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception {
messageDigest = MessageDigest.getInstance(algorithmName);
}
public void setAlgorithmName(String algorithmName) {
this.algorithmName = algorithmName;
}
}
---------------------------------------------------------------------------
import java.security.MessageDigest;
public class MessageDigester {
private MessageDigest digest1;
private MessageDigest digest2;
public void setDigest1(MessageDigest digest1) {
this.digest1 = digest1;
} // SHA1
public void setDigest2(MessageDigest digest2) {
this.digest2 = digest2;
} // MD5
public void digest(String msg) {
System.out.println("Using digest1");
digest(msg, digest1);
System.out.println("Using digest2");
digest(msg, digest2);
}
private void digest(String msg, MessageDigest digest) {
System.out.println("Using alogrithm: " + digest.getAlgorithm());
digest.reset();
byte[] bytes = msg.getBytes();
byte[] out = digest.digest(bytes);
System.out.println(out);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="shaDigest" class="com.apress.prospring5.ch4.MessageDigestFactoryBean"
p:algorithmName="SHA1"/>
<bean id="defaultDigest"
class="com.apress.prospring5.ch4.MessageDigestFactoryBean"/>
<bean id="digester"
class="com.apress.prospring5.ch4.MessageDigester"
p:digest1-ref="shaDigest"
p:digest2-ref="defaultDigest"/>
</beans>
Pro Spring 5 (156 page)