I have a abstract class containing run() method and few children classes overriding run method with different implementation. There a custom annotation class also, each child class has this annotation with different value to distinguish each child class. I was to call this run method for each child class from abstract class object using these annotations without using child class name. Is it possible or there some other way to do this?
CODE IS HERE-------
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface CustomAnno {
public String name();
}
public abstract class AbstractClass {
abstract void run();
}
#CustomAnno(name="one")
public class ExtendingClassOne extends AbstractClass {
#Override
void run() {
System.out.println("class one extending");
}
}
#CustomAnno(name="two")
public class ExtendingClassTwo extends AbstractClass {
#Override
void run() {
System.out.println("class two extending");
}
}
So having abstract class and annotation values "one" and "two", can I call run method for each child class without using child class name.
We can use ClassPathScanningCandidateComponentProvider spring library to list all the classes that use a particular kind of annotation. Here annotations can be custom or default one. So putting annotations on all child classes that extend that abstract class can give list of only those child classes only. This solved my problem.
Related
I have a Interface I and a Abstract Class A , I have My custom annotation MyAnnotation which should take parameter as subclass S of A, now while processing annotation I want to call method of concrete class S
public interface I{
void m1();
}
public abstract class A implements I {
public abstract void m1();
}
public #interface MyAnnotation {
public Class< ? extends A> ref();
public Class< ? super A> ref2();
}
public S extends A{
public void m1() {}
}
I am annotating method like
#MyAnnotation(ref= new XX() ) or #MyAnnotation(ref= XX.class )
#MyAnnotation(ref= new yy() ) or #MyAnnotation(ref= yy.class )
whichever works
//In spring aspect before processing I am getting method annotation and trying to call m1()
annotation.ref().m1() //Error
annotation.ref2().m1() //Error
You can't use new XX() in an annotation. Annotations parameters can use a very specific set of types:
primitive
String
Class
an Enum
another Annotation
an array of any of the above
See this answer.
So to accomplish what you're trying to accomplish, you'd have to use a class.
You would then have to use reflection to create an instance and invoke the method.
Class<?> clazz = annotation.ref();
I instance = (I) cls.getConstructor().newInstance();
instance.m1();
See this answer.
Your classes must all have no-argument constructors, else you'll only be able to instantiate some this way but not others (leading you to have to conditionally branch based on the class).
You can't do that simply like that. You need an instance of the class first.
If your A class is a Spring's bean, you can inject ApplicationContext and get the bean from there. Then you can call a method.
#Autowired
private ApplicationContext context;
void test(MyAnnotation annotation) {
A bean = context.getBean(annotation.ref());
bean.m1();
}
I have a parent class called BaseService and I have other services that inherit from BaseService as they all need those methods to do their jobs. As always the methods of the superclass are available inside the subclass... However, when I use #Autowired DI to inject the subclass I am not able to use the methods defined by the parent class, I am only able to use what is defined separately in the subclass. How can I inject the subclass and have it properly instantiate the subclass such that the methods of the parent class are available to me?
Ex. Parent Class
#Service
public class BaseService{
public BooleanExpression combineBools(Predicate predicate, BooleanExpression bool){
BooleanExpression result = runupBool.and(predicate);
return result;
}
}
Ex. Child Class
#Service
public class EqServiceImpl extends BaseService implements EqService{
public EqServiceImpl(){
super();
}
#Override
public Iterable getAllData(Map<String, String> params, Predicate predicate) {
// Some Method Specific to Child Class
}
}
Ex. Controller
#RestController
public class EqController {
#Autowired
EqService eqService
...
}
If I wanted to access the method eqService.combineBools() inside the controller I am unable to. Why is this? How can I fix it?
As DarrenForsythe pointed out I am instantiating with EqService as the type so it would not have all of the methods of the BaseService since it does not extend that class, rather it is the EqServiceImpl that extends that class. Therefore I would need the type to be EqServiceImpl. Without making some other changes #Autowired is not the best choice for DI here.
Imagine there is class
public class sample {
private String fieldName;
}
Which already compiled and the part of the claspath when the jam statsup.
I want add #notnull and #size(min=1,max=5) dynamically for fieldName(not class level)
Any suggestions plz
I'll try to answer the question as a ByteBuddy question, without the synopsis of validation.
Using ByteBuddy, you can change your classes at runtime. But in certain conditions, like you are not on Android (Dalvik's virtual machine is different than ordinary JVMs), and you shouldn't change an already loaded class.
class Subclass {
public void func() {
}
}
class FunctionalInterfaceImpl implements FunctionalInterface {
#Override
public Class<? extends Annotation> annotationType() {
return FunctionalInterface.class;
}
}
public class TryingByteBuddy {
public static void main(String[] args) {
new ByteBuddy()
.redefine(TypePool.Default.ofClassPath().describe("com.experiments.Subclass").resolve(),
ClassFileLocator.ForClassLoader.ofClassPath())
.annotateType(new FunctionalInterfaceImpl())
.make()
.load(ClassLoader.getSystemClassLoader());
System.out.println(Arrays.deepToString(new Subclass().getClass().getAnnotations()));
}
}
In this code Subclass is a class that doesn't have the #FunctionalInterface annotation. Now when you run you will find it has it.
NOTES ON THIS CODE:
You will find that we didn't use Subclass.class when trying to redefine the class
This is to prevent loading of the class before creating the alternative
Using Subclass.class will invoke the class loader to load the original class, this prevents ByteBuddy from doing its work
We "implemented" the annotation interface we want to add (FunctionalInterface in this example).
For more info:
ByteBuddy tutorial
I have an interface A:
public interface Parent {
method1()
}
And an interface B:
public interface Child extends Parent{
method2()
}
Of course there is a class that implements interface B:
public class implements B{
#Override
method1(){
}
#override
method2(){
}
}
Now in a concrete class X, I use Spring autowiring to inject the interface "Parent":
public class X{
#Autowired
Parent parentImpl;
someMethod(){
}
)
But when I use the instance parentImpl, I only get access to method1
How can I get access to method2 in this case?
Thanks.
If you inject the interface Parent, there's no way to access method2() because it is only known in interface Child and not in Parent.
But if you inject a variable of interface Child in class X, then method2() would be accessible.
It is not a problem of Spring or Autowiring but of interfaces and implementations.
Field parentImpl has type Parent, so you can invoke only Parent's methods.
If you want to be able to invoke Child's methods you should #Autowired Child interface
This is not really a Spring question but Java question.
If you know that your concrete class can be of the sub interface you can cast it:
((Child)impl).method2();
You should check that your impl class is of the sub interface
if (impl instance of Child) {
((Child)impl).method2();
}
However, I don't think it is a good practice, what are you trying to achieve?
If you ignore Spring and Autowiring, you will have the same problem.
public class X {
private Parent parentImpl; //this is declared as a Parent.
public void someMethod() {
//This will see parentImpl as type Parent
//because that is how it is declared in this class.
}
)
If you want to be able to see parentImpl as a Child type, then it should be declared as such.
I have a Class called Module which has a Method onEnable();
Now i have a class called Config and want to make the onEnable(); method private because there is a predefined acting and a class extending Config should'nt be allowed to change the behaviour.
Is there any way to do this?
Example
class Module{
public void onEnable(){
}
}
A class extending Module which is allowed to use onEnable:
class HelloWorldModule{
#Override
public void onEnable(){
System.out.println("Hello, World!");
}
}
Now the config Class, where i want that onEnable is private so that Classes which extend Config cannot! Override onEnable:
class Config{
#Override
private void onEnable(){
}
}
So NOW, a class named ProgrammConfig which extends Config cannot override onEnable.
However, this is not working because you cannot override a public method to a private method.
By declaring a method as public, you are saying that it should be possible to call said method on every instance of this class, including subclasses. Declaring a method as private in a subclass doesn't make sense, and is thus not allowed.
Now, if you're concerned about subclasses overriding the method, you can declare the method as final to prevent this:
class Config extends Module{
#Override
public final void onEnable(){}
//Whatever
}
You cannot solve this using inheritance. If Config is a subclass of Module, then it must provide all functions of Module with (at most) the same access restrictions. Think of a subclass as a specialized version of the superclass: It can do everything the superclass can, likely more, but never less.
Still you can implement a Config class as desired. Just skip subclassing, and instead use a private field of type Module like so:
class Config {
private Module module;
public Config() {
module = new Module();
}
public int SomeFunctionFromModuleYouWantToExpose() {
return module.SomeFunctionFromModuleYouWantToExpose();
}
// ...
}