I hope I have chosen a title as clear as possible.
I have classes annotated with a custom annotation
#MyAnnotation
public class MyClass1 {
//...
}
#MyAnnotation
public class MyClass2 {
//...
}
I have another class that I want to enrich with two methods with the same name:
one method that takes only the annotated class as parameters, and the other method that takes other classes as parameters
public class MyOtherClass {
public void myMethod(Object obj) {
//.....
}
public void myMethod (#MyAnnotation Object obj) {
// this method is applied for only classes annotated with #MyAnnotation
}
}
I know that public void myMethod (#MyAnnotation Object obj) is a wrong way we can not pass annotation as parameter. But I want to find the proper way to handle this need.
You can have a single myMethod(Object obj) and inside it manually check if the obj passed to this method was annotated with #MyAnnotation (supposing that the retention policy is to keep it at runtime). Then dispatch calls to some private void processAnnotated(Object obj) and private void processNotAnnotated(Object obj) based on the result.
public void myMethod(Object obj) {
if (obj != null && obj.getClass().isAnnotationPresent(MyAnnotation.class)) {
processAnnottated(obj);
} else {
processNotAnnottated(obj);
}
}
I am not sure what you are trying to achieve. As you say, you can't annotate a parameter. You can mark an annotation as Runtime, but then you can only check with reflection if an annotation is present or not. So you could start myMethod with a call to a private validation method validateMyAnnotationIsSet(parameter) that checks if the annotation is set on the given class or not.
Perhaps it's better however to work with a MarkerInterface. You can create an empty interface that the class may or may not implement. Within your method you can accept that interface as parameter and then do an 'instanceof' and a cast to continue to work with it.
Related
In Byte Buddy tutorial at the time of this writing, everything is explained but a simple after and before method interceptor is not there as I explained below, am I missing something or tutorial is complex. (See LoggerInterceptor example gives method but not object, ChangingLoggerInterceptor example gives object but not invoked method)
What I wanted to achieve is to call a method of an object after its setter method executions. How can I write an interceptor and use it in Java 6?
public class DirtyClass{
private String _sField;
private boolean _bDirty;
public void setField(String sField) {
_sField = sField;
//setDirty(true); to be appended after proxying
}
public String getField() {
return _sField;
}
public void setDirty(boolean bDirty){
_bDirty = bDirty;
}
public boolean isDirty(){
return _bDirty;
}
}
DirtyClass d = new ByteBuddy().subclass(DirtyClass.class)...???
d.setField("dirty now");
System.out.println(d.isDirty()); //Expecting true
You can implement such a mechanism even without a method delegation as follows:
DirtyClass d = new ByteBuddy()
.subclass(DirtyClass.class)
.method(isSetter().and(not(named("setDirty"))))
.intercept(SuperMethodCall.INSTANCE.andThen(
MethodCall.invoke(DirtyClass.class.getMethod("setDirty", boolean.class))
.with(true)
)).make()
.load(DirtyClass.class.getClassLoader())
.getLoaded()
.newInstance();
This way, every setter is overridden to first invoke its super method and then to invoke the setDirty method with true as an argument. The linked example in the comments should however work as well.
An interceptor could look like the following (given that some interface Dirtiable is implemented):
public class Interceptor {
public static void getter(#SuperCall Runnable zuper, #This Dirtiable self) {
zuper.run();
self.setDirty(true);
}
}
This assumes that the instrumented super class implements the Dirtiable interface which can be done using .implement(Dirtiable.class) where the method can be implemented to set a field using the FieldAccessor implementation.
I'm trying to reduce some code duplication. Currently i got two methods that are almost identical, the major difference being calling two separate methods within them.
Below is basically what i wanna do:
private void combinedMethod(StandardClass sc, MyClass mc)
{
Method m = null;
if(mc instanceof MySubClass1)
m = sc.RelevantFor1();
if(mc instanceof MySubClass2)
m = sc.RelevantFor2();
m(mc.getA(), mc.getB());
}
I've tested (and it works) this using reflection. But is there a better way of doing it? I read somewhere that reflection is slow and only to be used as a last resort. Is it in this case?
Also in this case the StandardClass is a standard class in the java api. The Class I send in is of my own making.
It isn't clear how exactly those methods look like, or what they are doing, but it seems like a perfect polymorphism case. You can create a method in super class - MyClass I suppose in this case. And override those methods in your subclasses.
Now, when you call that method on MyClass reference, appropriate subclass method will be called based on actual instance. Now invoke whatever method you want to invoke in respective overridden methods.
Somewhere along the lines of:
class MyClass {
public void method(StandardClass sc) { }
}
class MySubClass1 extends MyClass {
public void method(StandardClass sc) {
sc.method(getA(), getB());
}
}
class MySubClass2 extends MyClass {
public void method(StandardClass sc) {
sc.anotherMethod(getA(), getB());
}
}
And then your combinedMethod looks like:
private void combinedMethod(StandardClass sc, MyClass c) {
c.method(sc);
}
Is there a way in java to write a method which will take an unknown object as a parameter? The objects will always have a common method which the method will then need to call. Here is an example:
public void aMethod (MultipleObjects object){
object.commonMethod();
// Do some stuff here
}
I'm not sure what this is called (if it exists) so its difficult to search on Google.
You need an interface:
interface MyInterface {
void commonMethod();
}
class MyClass implements MyInterface {
// implement `commonMethod()`
}
Now your method would be:
public void aMethod(MyInterface object) {
...
object.commonMethod();
...
}
You can now pass an instance of MyClass (or any other class that implements MyInterface) to aMethod().
You can make all those classes (which share the common method) to implement an interface, so you define the method like:
public void aMethod(SomeInterface obj) {
obj.commonMethod();
// ...
}
The interface would be:
public interface SomeInterface {
public void commonMethod();
}
The usual way to do this is to define an interface that has just that method in it, then make sure all the classes that you might pass to aMethod implement that interface. E.g.:
interface CommonMethodHaver {
void commonMethod();
}
class Class1 implements CommonMethodHaver {
yadda yadda yadda;
void commonMethod() {
do class1-specific stuff here;
}
}
...
public void aMethod(CommonMethodHaver cmh) {
cmh.commonMethod();
// Do some stuff here
}
If you truly don't know what objects will be passed in and those object are not related through any kind of common base class or interface, then you will need to pass the object in as an Object reference and use reflection to find out if the object implements the method you want to call. If it does, then you again use reflection to call it.
I understand a lot of people are interpreting your question to mean you want to know about interfaces but I am interpreting this "write a method which will take an unknown object as a parameter?" to mean how do I write a method to handle unknown objects. As the other answers already tell you unless they share a common interface you can't have them all call the same method. But in case you are asking for this(which is what I think your question is asking for) this is how you would custom handle different unknown parameters...
public void aMethod(Object... object) {
if(object==null)
{
//whatever you want to do if no parameters are entered.
return;
}
for (Object o : object) {
if (o == null) {
continue; //what to do if null entered
}
if (o instanceof Integer) {
//whatever you want to do if it is an Integer
}
else if(o instanceof Double)
{
//whatever you want to do if it is a Double
}
else if(o instanceof Character)
{
//whatever you want to do if it is a Character
}
//and so on
}
}
I have an object model made up of interfaces with getter/setter methods. Implementations of these objects are created using dynamic proxies where values for the fields implied (using JavaBean naming conventions) are stored in a Map.
I'd like to add methods to these interfaces to provide business logic (you know, like a real object model and not just a collection of POJOs).
My first thought was to create abstract classes that implement each interface but only provide implementations of the business methods. Then I would use these implementations in concert with the Map in the InvocationHandler to provide a full implementation of the interface.
Something like:
interface ModelObject extends BaseModel {
void setFoo(String foo);
String getFoo();
void doSomething();
}
public abstract class ModelObjectImpl implements ModelObject {
#Override
public void doSomething()
{
// Do something
}
}
public class ModelObjectInvocationHander implements InvocationHandler {
Map<String, Object> fieldValues; // holds values for implied fields for getter setter
ModelObject modelObject; // holds reference to object implementing business methods
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Get implied field name for method name by removing "get"/"set" and lower casing next letter
String fieldName = getBeanNameForMethod(method.getName());
if (fieldValues.containsKey(fieldName)) {
return fieldValues.get(fieldName);
}
// Not a getter/setter so must be a business method. Delegate to implementation class
return method.invoke(modelObject, args);
}
}
Something like this (but obviously more complicated) would work except that I cannot create an instance of the abstract class. I could make BusinessObjectImpl non-abstract and add do-nothing implementations of the getter/setter methods that would never be called, but that just uglies up the code and causes maintenance issues. I could also have BusinessObjectImpl not actually implement the BusinessObject interface but that breaks the nice binding between implementation and interface leading to errors when the interface and "implementation" get out of sync.
Are there any sneaky Java Reflection tricks I can use to invoke these business methods?
UPDATE:
Went with a combination of the Java dynamic proxy framework that's already in place and Javassist to create proxies for the abstract implementation classes. This allows there to be no changes at all to the existing model interfaces until business methods are added on an as-needed basis. The capability is now in place to add behavior to the objects. It's up the developers to start writing true object oriented code now.
public class ModelObjectInvocationHandler implements InvocationHandler
{
public ModelObjectInvocationHandler(Class<ModelImplementation<? extends BaseModel>> implementationClass)
{
if (implementationClass != null)
{
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(implementationClass);
try
{
modelObject = (ModelObject) factory.create(new Class<?>[0], new Object[0]);
}
catch (Exception e)
{
// Exception handling
}
}
}
Map<String, Object> fieldValues; // holds values for implied fields for getter setter
ModelObject modelObject; // holds reference to object implementing business methods
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// Get implied field name for method name by removing "get"/"set" and lower casing next letter
String fieldName = getBeanNameForMethod(method.getName());
if (fieldValues.containsKey(fieldName))
{
return fieldValues.get(fieldName);
}
// Not a getter/setter so must be a business method. Delegate to implementation class
if (modelObject != null)
{
return method.invoke(modelObject, args);
}
return null;
}
}
At runtime, I scan for implementation classes and create a Map<Class<? extends BaseModel>, Class<ModelImplementation>>. When creating the dynamic proxy for the interface, I find its implementation class in the map and pass it to the InvocationHandler. Any method that is not matched as a bean name is delegated to the proxy for the implementation class. Of course, it's a little more complicated than that since I have to account for class hierarchies and multiple inheritance within the model interfaces, but the theory is sound.
I'm not aware of any standard Java reflection tricks that would do that. You could dynamically extend the abstract classes using cglib or javaassist at class load-time. This would improve performance a little bit, because no Proxy object is necessary anymore. Instead you can implement the getter/setter methods directly when creating the new class.
A third way, without those tricks, would be with the delegation pattern:
public class ModelObjectImpl implements ModelObject {
private final ModelObject delegate;
public ModelObjectImpl(ModelObject delegate) {
this.delegate = delegate;
}
#Override
public void doSomething() { /* Do something */ }
#Override
public String getFoo() { return delegate.getFoo(); }
#Override
public void setFoo(String foo) { delegate.setFoo(foo); }
}
Feed your proxy, implementing the getter/setter methods of the interface, to the constructor delegate argument. However, while this looks better than stub methods (at least for me) it's still duplicate code. So if you really want to have such dynamic classes, go with dynamic bytecode generation.
References:
Delegation pattern
CGLib
Javaassist
One way to do that is to define all your "additional" or "business" method's contract in a new interface, like:
interface ModelObjectExtension {
void doSomething();
}
interface ModelObject extends ModelObjectExtension {
void setFoo(String foo);
String getFoo();
}
public abstract class ModelObjectExtensionImpl implements ModelObjectExtension {
#Override
public void doSomething()
{
// Do something
}
}
public class ModelObjectImpl extends ModelObjectExtension {
// whatever your current implementation is...
}
and finally you can use following in your handler to call extension methods:
((ModelObjectExtension) modelObject).doSomething();
I have annotation like #SecureObject, which might be applied to some classes. Additionally there is the ORM, which provides method like
public ObjectID get(Class paramClass, Object object);
Now I need to create aspect, which will be triggered only in case if paramClass is annotated with #SecureObject.
Straightforward solution like:
#Before("call(public * some.orm.Datastore.get(..,#SecureObject *,..))"
void runBefore() {
// method code
}
does not work - method is never invoked. but wired (checked with aspectj -debug).
Is it possible to achieve such behavior with AspectJ, and if so - how?
The problem is that the first parameter of your get() method is of type Class.
Given that, you can't use an annotation-based method signature pattern. One possible solution is to use an if() pointcut expressions:
package aspects;
#Aspect
public class MyAspect {
#Pointcut("if() && call(public * some.orm.Datastore.get(..)) && args(paramClass,..)")
public static boolean runBefore(JoinPoint jp, Class paramClass) {
return paramClass.isAnnotationPresent(annotation.SecureObject.class);
}
#Before("runBefore(jp, paramClass)")
public void runBeforeAdvice(JoinPoint jp, Class paramClass) {
System.out.println("annotated!");
}
}
Note: This pointcut also triggers if no #SecureObject annotation is present but the if() condition gets evaluated at runtime.