Re: New Reflection/Beans API
"Stephen Colebourne" <[email protected]>
| Newsgroups | gmane.comp.jakarta.bcel.devel |
|---|---|
| Message-ID | <002601c20b0f$06f91f80$e54d18d4@oemcomputer> |
Hi,
Well, you'll never guess what I've been working on today...
My interest in this comes from the Joda project (www.joda.org). There I am
developing code which aims to build upon the current JavaBean spec and to
provide more functionality. Already working are Java (non-BCEL) versions of
an API. However, there are places where it is slow, and it is memory hungry.
This is where I have started to use BCEL (I've only started today, so I
haven't got too far yet).
The API includes a Bean interface which is to be implemented by all beans.
This provides access to each property of the bean:
interface Bean {
Map getPropertyMap();
Property getProperty(String propertyName);
Class getBeanType();
Object cloneDeep();
}
interface Property {
void set(Object object);
Object toObject();
boolean isReadOnly();
boolean isModifiable();
void setReadOnly();
void setModifiable(boolean);
String getPropertyName();
Class getPropertyType();
String getContentName();
Class getContentType();
boolean equalsValue(Object object)
void addPropertyChangeListener(PropertyChangeListener)
void removePropertyChangeListener(PropertyChangeListener)
void firePropertyChange(Object from, Object to)
}
> Possible features:
> ------------------
> * Property objects (i.e. bound to a particular object field)
> * Read-only properties
> * Automagically generated setters, getters, event methods, etc.
> * Generate BeanInfo's for Introspection
> * Generate Beans for alternate sources (XML, DB tables)
> * Collection handling
I agree with most of these. BeanInfo is more trouble than its worth. XML/DB
can build upon the architecture rather than needing to be BCELed in at a low
level. I would also add
* Allow properties to be added by applications on demand
* Generate from an interface, abstract class or real class
For interfaces and abstract methods, things are easy - just generate code
according to some default setup. But a factory is required to actually
create the objects - and people hate factories (and beans really should have
a no-args public constructor)
Thus a normal class would need to be modified on load. My thought was that
any options could be set as API calls with the method being replaced.
public void setSurname(String surname) {
// some application logic
BeanGen.createSet(flags);
// some application logic
}
Well, thats what I'm looking at anyway ;-)
Reflection
----------
I'm more interested in the Beans side, but...
For statics, isn't it a case of passing null in where the object ref would
go? That's what Java reflction does.
Stephen
----- Original Message -----
From: Markus Dahm <[email protected]>
To: <[email protected]>
Sent: Monday, June 03, 2002 3:27 PM
Subject: New Reflection/Beans API
> Hi,
>
> recently there has been some discussion about how to design/implement
> an Reflection and Bean API using BCEL. Since I think it would be a
> very good idea to have such a thing in BCEL, I'd like to start a
> discussion here about the requirements and implementation issues.
>
> This is not a real proposal, just a collection of thoughts and ideas
> where I took some from a previous posting by Stephen Colebourne.
>
> Reflection:
> -----------
>
> How it should work is obvious (!?), we add some code to the class that
> is to used be used reflectively. We could do this statically, i.e., in
> some kind of compiler, or using a class loader, which may be a little
> less performant, but is of course much more flexible.
>
> The benefits of such an API would be
>
> a) increased performance of reflection (measurements?)
>
> b) additional features possible, e.g., we could have a class loader
> that allows to run a chain of class modifiers, where adding reflexive
> behaviour would be just one. I.e., such class modifiers would have a
> method
>
> public JavaClass modifyClass(JavaClass clazz) { ... }
>
> c) base for a Beans API
>
> The question is how to tell which classes need to be augmented. This
> has to be know statically since we only have one chance to augment the
> class, namely when it is loaded/created. The simpliest approach would
> be to require the class to implement a marker interface, say
>
> public interface Reflective {}
>
> The other possibility would be to tell the class loader, before the
> class gets loaded, e.g., via some regular expression:
>
> cl.addReflectiveClass("com.foo.beans.*Impl");
>
> One could also restrict access to certain methods and fields.
>
> --------------------------------------------------------------------------
------
>
> Given that we want to modify class A
>
> public class A implements Reflective {
> private String str;
> private int x;
>
> int foo() { }
> int foo(int x) { }
> }
>
> We would then like to use reflection like this:
>
> A a = new A();
> JavaClass clazz = Repository.lookupClass("A");
> Field[] fields = clazz.getFields();
> Method[] methods = clazz.getMethods();
>
> fields[0].setValue(a, "Hello world");
> Object result = methods[i].invoke(a, new Object[] { new
> Integer(4711); });
>
> Of course setValue/invoke would throw an exception if the passed
> object does not support our kind of reflection.
>
> public void setValue(Object target, Object value) throws SomeException
{
> if(target instanceof BCELReflective) {
> ((BCELReflective)target).BCELsetValue(target, field_name, value);
> } else if(target == null) { // Access to static field
> ??????????????
> }
> }
>
> However, we have our first problem here: How does this work for static
> fields and methods?
>
>
> As you probably already noticed the class loader or whatever would let A
> implement another interface and implement its methods:
>
> public interface BCELReflective {
> public void BCELsetValue(String name, Object value);
> public Object BCELgetValue(String name);
> public Object BCELinvoke(String name, Object[] args);
> }
>
> These methods would wrap/unwrap the arguments and call the
> corresponding methods or set/get the right field.
>
>
> Problems so far:
> ---------------
>
> * As we all know methods may be overloaded thus just using the name is
> not really sufficient here, instead we could use the method index or
> some generated identifier. Using the index would allow us to use a
> fast switch() statement.
>
> * Fields and methods currently do not know their index nor the
> JavaClass object they belong to. We could pass them in the
> setValue/invoke argument list.
>
> * How do we implement reflection for static fields and methods?
>
>
>
> Beans (Really just a scratch file of ideas):
> -------------------------------------------
>
> I'm not an expert on Java Beans, but probably many of you are...
>
> What we could have is an extension of ClassGen, say BeanGen that has
> additional methods and an extended InstructionFactory. I know there
> is a class somewhere the Java Bean API such as "BeanAdapter" which
> already implements the default behaviour and can be used as a
> delegatee. I.e., we can use this class in our API.
>
> What we obviously need is a declarative way to tell which features
> we want for our bean. Having an interface with empty methods is a
> very simple approach, but I think we need something more powerful.
> One problem is for example that property names need not to be
> equivalent to field names. Getters and setters may have additional
> checking code that relies on other fields.
>
> Possible features:
> ------------------
> * Property objects (i.e. bound to a particular object field)
> * Read-only properties
> * Automagically generated setters, getters, event methods, etc.
> * Generate BeanInfo's for Introspection
> * Generate Beans for alternate sources (XML, DB tables)
> * Collection handling
> * See below :)
>
> Cheers
> Markus
>
> P.S. The developer list is being archived now.
>
> --------------------------------------------------------------------------
-----
> The original positing from Stephen Colebourne
>
>
> Scope:
> Reflection - Class, Method, Field, ...
> Bean - Introspector, javabeans
>
> Need:
> - Performance on java1.3 and earlier
> - J2ME
> - Current reliance on javabean spec version 1 that was designed to replace
> ActiveX, not be a domain model.
> - Boring coding of javabean gets/sets (I know tools can help, but I still
> see bugs in gets and sets)
> - Auto generated event methods (bound/constrained properties)
> - Desire for dynamicly created javabeans/ properties (from databases, xml
> etc.)
> - Desire to pass around an object representing a property
> - Desire to change the bean Introspector's lookup mechanism, such as to
> allow private get/set methods to be treated as properties
> - Desire to handle collections properly (they aren't handled at all by
beans
> Introspector at the moment
> - Desire to dynamically make a property read only once setup (like const
in
> C)
>
> Bean types:
> - Coder writes interface with coded get and set methods, BCEL generates
> implementation on the fly
> - Coder writes abstract class with coded get and set methods, BCEL
generates
> implementation on the fly
> - Coder writes real class with coded get and set methods, BCEL modifies
> parts on the fly
> - A general purpose bean, to be used where all the data is dynamic,
similar
> to a HashMap
> - A mixture object, where some fields have coded get and set methods,
others
> are dynamically created as the application requires
>
>
> OK, so if you haven't guessed, I'm more interested in Beans than
Reflection
> on its own (Reflection is fine and useful, but its very low level). Most
of
> these ideas come from the Joda project, but I think they represent a good
> idea of what people are using beans for now.
>
> Stephen
>
>
> --
> To unsubscribe, e-mail: <mailto:[email protected]>
> For additional commands, e-mail: <mailto:[email protected]>
>
>