Ngữ cảnh của Bean

Chúng ta tiếp tục tìm hiểu cách tạo ra các Bean để tận dụng được các thế mạnh cùa chúng. Vấn đề cơ bản là cài đặt các Bean để chúng tương tác được với các Bean khác hoặc sừ dụng được các dich vụ mà BeanBox cung cấp. Muốn thế ta phải biết được ngữ cành cùa Bean. Ngữ cảnh của Bean chứa các Bean, các dịch vụ và ngữ cảnh Bean khác, giống như bộ chứa Container cùa AWT. Ví dụ BeanBox của BDK1.1 chính là một ngữ cảnh cúa Bean. Nó cung cấp dịch vụ theo dõi các vết cùa việc hiển thị các thông điệp.

Đe Bean trao đổi được với ngữ cảnh xung quanh, nó phải cài đặt giao diện BeanContextChild. Giao diện này đã khai báo:

void setBeanContext(BeanContext bc)

BeanContext getBeanContext(BeanContext bc)

void addPropertỵChangeListener(String name,

PropertyChangeListener listener)

void removePropertyChangeListener(String name,

PropertyChangeListener listener)

void adđVetoableChangeListener(String name,

VetoableChangeListener listener)
void removeVetoableChangeListener(String name,
VetoableChangeListener listener)

Ngữ cảnh cùa Bean sẽ gọi setBeanContext 0 khi nó bắt đầu quản lý các Bean. Công việc cài đặt các phần tử lắng nghe các sự kiện thay đổi của các thuộc tính là khá vất vả, nên tốt nhất là sù dụng lớp BeanContextChìldSupport đề cài đặt chúng. Nhưng Bean cùa ta không thể đồng thời kế thừa một lớp thành phần và BeanContextChildSupport, nên ta phải thực hiện theo một cơ chế đặc biệt như sau:

  1. Cài đật giao diện BeanContextProxỵ
  2. Tạo ra đối tượng của BeanContextChildSupport

private BeanContextChildSupport chìldSupport = new BeanContextChildSupport();

  1. Viết hàm getBeanContextProxy () để nhận lại đối tượng được tạo ra

public BeanContextChildSupport getBeanContextProxyO{ return childSupport;

}

  1. Gọi getgetBeanContext () để xác định được ngữ cảnh của nó BeanContext context = childSupport.getBeanContext();

Các lớp nêu trên có quan hệ với nhau như hình 5.4

Ví dụ 5.5. Hãy xét một spin Bean, một phẩn tử điều khiển nhỏ có hai nút Button để tăng hay giảm một giá trị.

Tự bản thân spin Bean thì chẳng hữu dụng. Nó cần phài cặp bộ vời Bean khác. Vỉ dụ, khi cặp bộ với IntTextBean chứa các giá trị nguyên, thì giá trị số nguyên sẽ tăng lên l khi nhấn nút ‘+’, hoặc giản khi nhấn nút // SpinBean.java import java.awt.*; import java.awt.event.*; import java.beans.*; import java.beans.beancontext.* ; import java.lang.reflect.*; import java.io.*; import java.util.*; import javax.swing.*;

public class SpinBean extends JPanel implements Serializable,

BeanContextProxy! public SpinBean(){

setLayout(new GridLayout(2, 1));

JButton plusButton = new JButton(“+”);

JButton minusButton = new JButton(“-“); add(plusButton); add(minusButton);

plusButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent evt){ spin (1);

}

}) ;

minusButton. addActionListener (new ActionListener() { public void actionPerformed(ActionEvent evt){ spin(-1);

}

}) ;

childSupport = new BeanContextChildSupport (){

public void setBeanContext(BeanContext context) throws PropertyVetoException{ super.setBeanContext(context); setTracer(context);

}

};

}

public BeanContextChild getBeanContextProxy(){ return childSupport;

}

public void setBuddy(Component b, PropertyDescriptor p){ buddy = b; prop = p;

}

public void spin(int incr){ if(buddy == null) return; if(prop == null) return;

Method readMethod = prop.getReadMethod();

Method writeMethod = prop.getWriteMethod(); try {

int value = ((Integer) readvfetbod. invoke (buddy, null)). intValue () ; if (tracer != null){

String text = “spin: value ='” + value + “increment = ” + incr;

Method logText – tracerClass. getMethcd (“logText”, new Class[] {String.class}); logText. invoke (tracer, newCbject[] {text});

}

value += incr; writeMethod.invoke(buddy,

new Obj ect[]   {new Integer(value) });

}catch(Exception e){

}

}

public void setTracer(BeanContext context){ try {

BeanContextServices services

= (BeanContextServices) context; tracerClass = Class.forName

(“sunw.demo.methodtracer.MethodTracer”); if(services.hasService(tracerClass)){

BeanContextServiceRevokedListener revokedListener = new BeanContextServiceRevokedListener(){ public void serviceRevoked(

BeanContextServiceRevokedEvent event){ tracer = null;

}

};

tracer = services.getService(childSupport, this, tracerClass, null, revokedListener);

}catch(Exception e){ tracer = null;

}

}

public Dimension getPreferredSize(){

return new Dimension(MINSIZE, MINSIZE);

}

private static final int MINSIZE = 20; private Component buddy; private PropertyDescriptor prop; private Object tracer; private Class tracerClass;

private BeanContextChildSupport childSupport;

}

// SpinBeanCustom.java

import j ava.awt.* ;

import j ava.awt.event.* ;

import j ava.beans.*;

import j ava.beans.beancontext. * ;

import j ava.text.*;

import java.io.*;

import java.util.*;

import j avax.swing.*;

import j avax.swing.event.*;

public class SpinBeanCustom extends JPanel implements Customizer{

private SpinBean bean;

private PropertyChangeSupport support

= new PropertyChangeSupport(this); private JList buddyList; private JList propList; private DefaultListModel buddyModel; private DefaultListModel propModel; private PropertyDescriptor[] props; private Component!] buddies;

public SpinBeanCustom(){

setLayout(new GridBagLayout());

GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 0; gbc.weighty = 100;

gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.EAST; add(new JLabel(“Buddy”), gbc, 0, 0, 1, 1); addfnew JLabel(“Property”) , gbc, 0, 1, 1, 1); gbc.weightx = 100;

gbc.fill = GridBagConstraints.WEST; gbc.anchor = GridBagConstraints.BOTH;

buddyModel = new DefaultListModel(); propModel = new DefaultListModel(}; buddyList = new JList(buddyModel); propList = new JList(propModel);

add(new JScrollPane(buddyList), gbc, 1, 0, 1, 1); add(new JScrollPane(propList), gbc, 1, 1, 1, 1); JButton setButton = new JButton(“Set Buddy”); JPanel p = new JPanel() ; p.add(setButton); add(p, gbc, 0, 2, 2, 1) ;

buddyList.addListSelectionListener( new ListSelectionListener () {

public void valueChanged(ListSelectionListener evt)( findBuddyMethods();

}

}) ;

setButton.addActionListener( new ActionListener(){

public void actionPerformed(ActionEvent evt){ int buddylndex = buddyList.getSelectedlndex(); if (buddylndex < 0) return; int proplndex = propList.getSelectedlndex(); if (proplndex < 0) return;

bean.setBuddy(buddies[buddylndex], props[proplndex]);  1

}

}) ;

}

public void add (Ccmponent c, GridBagConstraints gbc, int X, int y, int w, int h){ gbc.gridx = x; gbc.gridy = y;

gbc.gridwidth = w; gbc.gridheight = h; add(c, gbc);

}

public void findBuddyMethods(){

int buddylndex = buddyList. getSelectedlndex () ; if(buddylndex < 0) return;

Component buddy = buddies[buddylndex]; propModel.removeAllElements(); try {

Beanlnfo info

= Introspector.getBeanlnfo(buddy.getClass()); props = info.getPropertyDescriptors(); int j = 0;

for(int i = 0; i < props.length; i++){

Class propertyType = props [i] . getPropertyType () ; if(int.class.equals(propertyType)){

String name = props[i].getName(); propModel.addElement(name); props[j++] = props[i];

}

}

}catch(IntrospectionException e){}

}

public Dimension getPreferredSize(){ return new Dimension(300, 200);

}

public void setObject(Object obj){ bean = (SpinBean)obj;

BeanContext context

= bean.getBeanContextProxy().getBeanContext(); buddies = new Component[context.size()]; buddyModel.removeAllElements();

Iterator iter = context.iterator(); int i = 0;

while(iter.hasNext()){

Object buddy = iter.next(); if(buddy instanceof Component){ buddies[i] = (Component)buddy;

String classNarre = buddies[i] .getClassO ,getName(); buddyModel.addElement(className); i++;

}

}

}

public void addPropertyChangeListener (PropertyChangeListener 1) { support.addPropertyChangeListener(1);

}

public void reiovePrcpertiChangeListener (PropertyChangeListener 1)

{

support.removePropertyChangeListener (1);

}

}

//SpinBeanBeanlnfojava

impo rt java.awt.*; import java.beans.*;

public class SpinBeanBeanlnfo extends SimpleBeanlnfo{ public BeanDescriptor getBeanDescriptor(){ return new BeanDescriptor(SpinBean.class,

SpinBeanCustom.class);

}

}

Lớp java. beans, beancontext. BeanContexChilđ                        API

  • void setBeanContext (BeanContext be): được gọi khi đưa thêm một bean vào như là nút con.
  • BeanContext getBeanContext () : xác định ngữ cảnh của
  • void addPropertyChangeListener(String name,

PropertỵChangeListener listener): đưa thêm listener vào thuộc tính của bean.

  • void removePropertyChangeLístener(string name,

PropertyChangeListener listener): loại listener ra khòi thuộc tính cùa bean.

  • void addVetoableChangeListener(String name,

VetoableChangeListener listener): đưa thêm listener có khả năng phủ nhận vào thuộc tính cùa bean.

  • void removeVetoableChangeLístener(String name,

VetoableChangeLìstener listener): loại listener có khả nãng phủ nhận ra khỏi thuộc tính cúa bean