Let's take them one by one, but I should remind you that ASM's visitors can be chained very much the same way as SAX's handlers or filters. This sequence UML diagram shows class transformation, where green classes will be substituted by custom NotifierClassVisitor and NotifierCodeVisitor that will do the
actual bytecode transformation.

The code below uses NotifierClassVisitor to apply all required transformations.

Notice the true parameter in the ClassWriter constructor,
which enables the automatic calculation of maximum size of stack and local variables.
In this case, all values passed to the CodeVisitor.visitMax() method
will be ignored and ClassWriter will calculate these values
based on the actual bytecode of the method. However, the CodeVisitor.visitMax()
method still must be called, which happens in its default implementation in
CodeAdapter. This is important because, as you can see in the comparison
results, these values are different for changed bytecode, and with this flag
they will be recalculated automatically, covering item #6 in the list above.
The rest of items will be handled by NotifierClassVisitor.

The first difference appears in parameters of the visit method,
where the new interface should be added. The code below will cover item #1.
Notice that the cv.visit() method is called to redirect
the transformed processing event to the nested class visitor, which is
actually going to be a ClassWriter object.
We also need to save the class name, since it will be needed later.

All new elements can be added in the visitEnd()
method just before calling visitEnd() on the chained visitor.
That will cover items #2 and #3 from the list above. Notice that the class name
saved in the visit() method is used instead of a hard-coded constant,
which makes the transformation more generic.

The rest of the changes belong to method bytecode, so it's necessary
to overwrite the visitMethod() method.
There are two cases have to be covered:

Add instructions to call notify() method to all non-static methods.

Add initialization code to all <init> methods.

In the first case, new instructions are always added to the beginning of the method bytecode,
so chained CodeVisitor can be fired directly.
However, in case of the <init> method, instructions should be added
to the end of method, so they have to be inserted before visitInsn(RETURN),
meaning a custom CodeVisitor is required here. This is how
visitMethod() will look:

Similar to ClassAdapter, we can extend the CodeAdapter class
and overwrite only those methods that should change the stream of processing events.
In this case, we change the visitInsn() method to
verify if it is an event for the RETURN command and, if so, insert
required commands before delegating the event to the next CodeVisitor
in the chain.