BadPractice12 - SpotBugsExtensionForSpringFrameWork/CS5098 GitHub Wiki

Bug Name: Avoid accessing FactoryBean directly and invoking its getObject() manually, and let Spring do it for you

Description

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>

Solutions

Reference List

Pro Spring 5 (156 page)

⚠️ **GitHub.com Fallback** ⚠️