I found this example which I was able to adapt to the java-formatter:
https://ltekieli.com/creating-and-using-bazel-aspects/
I basically have an aspect that collects lists of files (like in the example) and a run_shell action within my custom rule that calls java-formatter. For the run_shell I needed to tell it to disable the sandbox so that it can modify the source files. Mildly sketchy but it seems to work.
Like in the example I have a macro that needs a one-liner to be added to each BUILD file to basically generate calls to the format rule for each target.
I was hoping there might be a better way to do this like where the aspect is enabled from the command line and then we don't require that each build file have a call to the rule. I was able to get close with that approach but the problem I ran into was that the aspect needs to declare outputs and if there's nothing depending on the outputs it never gets executed. I was trying to think if there's a way that I can transform the underlying target so that the aspect's output becomes an input to them, thus establishing a dependency of the target on the aspect. That'd avoid the need of the macro whose sole purpose is to create an extra target for each of the underlying targets. Doesn't seem to be the way aspects work, though?