⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractreflectivembeaninfoassembler.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.jmx.export.assembler;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.management.Descriptor;
import javax.management.JMException;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;

import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.jmx.support.JmxUtils;

/**
 * Extends the <code>AbstractMBeanInfoAssembler</code> to add a basic
 * algorithm for building metadata based on the reflective metadata of
 * the MBean class.
 *
 * <p>The logic for creating MBean metadata from the reflective metadata is contained
 * in this class, but this class makes no desicions as to which methods and
 * properties are to be exposed. Instead it gives subclasses a chance to 'vote'
 * on each property or method through the <code>includeXXX</code> methods.
 *
 * <p>Subclasses are also given the opportunity to populate attribute and operation
 * metadata with additional descriptors once the metadata is assembled through the
 * <code>populateXXXDescriptor</code> methods.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 1.2
 * @see #includeOperation
 * @see #includeReadAttribute
 * @see #includeWriteAttribute
 * @see #populateAttributeDescriptor
 * @see #populateOperationDescriptor
 */
public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBeanInfoAssembler {

	protected static final String FIELD_GET_METHOD = "getMethod";

	protected static final String FIELD_SET_METHOD = "setMethod";

	protected static final String FIELD_ROLE = "role";

	protected static final String ROLE_GETTER = "getter";

	protected static final String ROLE_SETTER = "setter";

	protected static final String ROLE_OPERATION = "operation";

	protected static final String FIELD_VISIBILITY = "visibility";

	/**
	 * Lowest visibility.
	 * Used for operations that correspond to accessors or mutators for attributes.
	 */
	protected static final Integer ATTRIBUTE_OPERATION_VISIBILITY = new Integer(4);

	protected static final String FIELD_CLASS = "class";

	protected static final String FIELD_LOG = "log";

	protected static final String FIELD_LOG_FILE = "logFile";

	protected static final String FIELD_CURRENCY_TIME_LIMIT = "currencyTimeLimit";

	protected static final String FIELD_DEFAULT = "default";

	protected static final String FIELD_PERSIST_POLICY = "persistPolicy";

	protected static final String FIELD_PERSIST_PERIOD = "persistPeriod";

	protected static final String FIELD_PERSIST_LOCATION = "persistLocation";

	protected static final String FIELD_PERSIST_NAME = "persistName";


	/**
	 * Default value for the JMX field "currencyTimeLimit".
	 */
	private Integer defaultCurrencyTimeLimit;

	/**
	 * Indicates whether or not strict casing is being used for attributes.
	 */
	private boolean useStrictCasing = true;

	private boolean exposeClassDescriptor = false;


	/**
	 * Set the default for the JMX field "currencyTimeLimit".
	 * The default will usually indicate to never cache attribute values.
	 * <p>Default is none, not explicitly setting that field, as recommended by the
	 * JMX 1.2 specification. This should result in "never cache" behavior, always
	 * reading attribute values freshly (which corresponds to a "currencyTimeLimit"
	 * of <code>-1</code> in JMX 1.2).
	 * <p>However, some JMX implementations (that do not follow the JMX 1.2 spec
	 * in that respect) might require an explicit value to be set here to get
	 * "never cache" behavior: for example, JBoss 3.2.x.
	 * <p>Note that the "currencyTimeLimit" value can also be specified on a
	 * managed attribute or operation. The default value will apply if not
	 * overridden with a "currencyTimeLimit" value <code>>= 0</code> there:
	 * a metadata "currencyTimeLimit" value of <code>-1</code> indicates
	 * to use the default; a value of <code>0</code> indicates to "always cache"
	 * and will be translated to <code>Integer.MAX_VALUE</code>; a positive
	 * value indicates the number of cache seconds.
	 * @see org.springframework.jmx.export.metadata.AbstractJmxAttribute#setCurrencyTimeLimit
	 * @see #applyCurrencyTimeLimit(javax.management.Descriptor, int)
	 */
	public void setDefaultCurrencyTimeLimit(Integer defaultCurrencyTimeLimit) {
		this.defaultCurrencyTimeLimit = defaultCurrencyTimeLimit;
	}

	/**
	 * Return default value for the JMX field "currencyTimeLimit", if any.
	 */
	protected Integer getDefaultCurrencyTimeLimit() {
		return this.defaultCurrencyTimeLimit;
	}

	/**
	 * Set whether to use strict casing for attributes. Enabled by default.
	 * <p>When using strict casing, a JavaBean property with a getter such as
	 * <code>getFoo()</code> translates to an attribute called <code>Foo</code>.
	 * With strict casing disabled, <code>getFoo()</code> would translate to just
	 * <code>foo</code>.
	 */
	public void setUseStrictCasing(boolean useStrictCasing) {
		this.useStrictCasing = useStrictCasing;
	}

	/**
	 * Return whether strict casing for attributes is enabled.
	 */
	protected boolean isUseStrictCasing() {
		return useStrictCasing;
	}

	/**
	 * Set whether to expose the JMX descriptor field "class" for managed operations.
	 * Default is "false", letting the JMX implementation determine the actual class
	 * through reflection.
	 * <p>Set this property to <code>true</code> for JMX implementations that
	 * require the "class" field to be specified, for example WebLogic's.
	 * In that case, Spring will expose the target class name there, in case of
	 * a plain bean instance or a CGLIB proxy. When encountering a JDK dynamic
	 * proxy, the <b>first</b> interface implemented by the proxy will be specified.
	 * <p><b>WARNING:</b> Review your proxy definitions when exposing a JDK dynamic
	 * proxy through JMX, in particular with this property turned to <code>true</code>:
	 * the specified interface list should start with your management interface in
	 * this case, with all other interfaces following. In general, consider exposing
	 * your target bean directly or a CGLIB proxy for it instead.
	 * @see #getClassForDescriptor(Object)
	 */
	public void setExposeClassDescriptor(boolean exposeClassDescriptor) {
		this.exposeClassDescriptor = exposeClassDescriptor;
	}

	/**
	 * Return whether to expose the JMX descriptor field "class" for managed operations.
	 */
	protected boolean isExposeClassDescriptor() {
		return exposeClassDescriptor;
	}


	/**
	 * Iterate through all properties on the MBean class and gives subclasses
	 * the chance to vote on the inclusion of both the accessor and mutator.
	 * If a particular accessor or mutator is voted for inclusion, the appropriate
	 * metadata is assembled and passed to the subclass for descriptor population.
	 * @param managedBean the bean instance (might be an AOP proxy)
	 * @param beanKey the key associated with the MBean in the beans map
	 * of the <code>MBeanExporter</code>
	 * @return the attribute metadata
	 * @throws JMException in case of errors
	 * @see #populateAttributeDescriptor
	 */
	protected ModelMBeanAttributeInfo[] getAttributeInfo(Object managedBean, String beanKey) throws JMException {
		PropertyDescriptor[] props = BeanUtils.getPropertyDescriptors(getClassToExpose(managedBean));
		List infos = new ArrayList();

		for (int i = 0; i < props.length; i++) {
			Method getter = props[i].getReadMethod();
			if (getter != null && getter.getDeclaringClass() == Object.class) {
				continue;
			}
			if (getter != null && !includeReadAttribute(getter, beanKey)) {
				getter = null;
			}

			Method setter = props[i].getWriteMethod();
			if (setter != null && !includeWriteAttribute(setter, beanKey)) {
				setter = null;
			}

			if (getter != null || setter != null) {
				// If both getter and setter are null, then this does not need exposing.
				String attrName = JmxUtils.getAttributeName(props[i], isUseStrictCasing());
				String description = getAttributeDescription(props[i], beanKey);
				ModelMBeanAttributeInfo info = new ModelMBeanAttributeInfo(attrName, description, getter, setter);

				Descriptor desc = info.getDescriptor();
				if (getter != null) {
					desc.setField(FIELD_GET_METHOD, getter.getName());
				}
				if (setter != null) {
					desc.setField(FIELD_SET_METHOD, setter.getName());
				}

				populateAttributeDescriptor(desc, getter, setter, beanKey);
				info.setDescriptor(desc);
				infos.add(info);
			}
		}

		return (ModelMBeanAttributeInfo[]) infos.toArray(new ModelMBeanAttributeInfo[infos.size()]);
	}

	/**
	 * Iterate through all methods on the MBean class and gives subclasses the chance
	 * to vote on their inclusion. If a particular method corresponds to the accessor
	 * or mutator of an attribute that is inclued in the managment interface, then
	 * the corresponding operation is exposed with the &quot;role&quot; descriptor
	 * field set to the appropriate value.
	 * @param managedBean the bean instance (might be an AOP proxy)
	 * @param beanKey the key associated with the MBean in the beans map
	 * of the <code>MBeanExporter</code>
	 * @return the operation metadata

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -