私はこれの小さなテスト実装を一緒に投げました。基本的な考え方はformat、フォーマット文字列、オブジェクトのマップ、およびそれらがローカルに持つ名前を呼び出して渡すことです。
次の出力は次のとおりです。
  私の犬はfidoという名前で、Jane Doeが飼っています。
public class StringFormatter {
    private static final String fieldStart = "\\$\\{";
    private static final String fieldEnd = "\\}";
    private static final String regex = fieldStart + "([^}]+)" + fieldEnd;
    private static final Pattern pattern = Pattern.compile(regex);
    public static String format(String format, Map<String, Object> objects) {
        Matcher m = pattern.matcher(format);
        String result = format;
        while (m.find()) {
            String[] found = m.group(1).split("\\.");
            Object o = objects.get(found[0]);
            Field f = o.getClass().getField(found[1]);
            String newVal = f.get(o).toString();
            result = result.replaceFirst(regex, newVal);
        }
        return result;
    }
    static class Dog {
        public String name;
        public String owner;
        public String gender;
    }
    public static void main(String[] args) {
        Dog d = new Dog();
        d.name = "fido";
        d.owner = "Jane Doe";
        d.gender = "him";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("d", d);
        System.out.println(
           StringFormatter.format(
                "My dog is named ${d.name}, and ${d.owner} owns ${d.gender}.", 
                map));
    }
}
注:これは、未処理の例外のためにコンパイルされません。しかし、それによってコードが非常に読みやすくなります。
また、コードで自分でマップを作成する必要があることは好ましくありませんが、ローカル変数の名前をプログラムで取得する方法がわかりません。それを行う最善の方法は、オブジェクトを作成したらすぐにマップに配置することを忘れないことです。
次の例は、例から必要な結果を生成します。
public static void main(String[] args) {
    Map<String, Object> map = new HashMap<String, Object>();
    Site site = new Site();
    map.put("site", site);
    site.name = "StackOverflow.com";
    User user = new User();
    map.put("user", user);
    user.name = "jjnguy";
    System.out.println(
         format("Hello ${user.name},\n\tWelcome to ${site.name}. ", map));
}
また、Velocityが何であるかわからないので、この回答が関連していることを願っています。
               
              
String.format("Hello %s", username);