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

📄 lazyinitproxyfactory.java

📁 Wicket一个开发Java Web应用程序框架。它使得开发web应用程序变得容易而轻松。 Wicket利用一个POJO data beans组件使得它可以与任何持久层技术相结合。
💻 JAVA
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.wicket.proxy;import java.io.InvalidClassException;import java.io.ObjectStreamException;import java.io.Serializable;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Arrays;import java.util.List;import net.sf.cglib.core.DefaultNamingPolicy;import net.sf.cglib.core.Predicate;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import org.apache.wicket.IClusterable;import org.apache.wicket.model.IModel;/** * A factory class that creates lazy init proxies given a type and a {@link IProxyTargetLocator} * used to retrieve the object the proxy will represent. * <p> * A lazy init proxy waits until the first method invocation before it uses the * {@link IProxyTargetLocator} to retrieve the object to which the method invocation will be * forwarded. * <p> * This factory creates two kinds of proxies: A standard dynamic proxy when the specified type is an * interface, and a CGLib proxy when the specified type is a concrete class. * <p> * The general use case for such a proxy is to represent a dependency that should not be serialized * with a wicket page or {@link IModel}. The solution is to serialize the proxy and the * {@link IProxyTargetLocator} instead of the dependency, and be able to look up the target object * again when the proxy is deserialized and accessed. A good strategy for achieving this is to have * a static lookup in the {@link IProxyTargetLocator}, this keeps its size small and makes it safe * to serialize. * <p> * Example: *  * <pre> * class UserServiceLocator implements IProxyTargetLocator * { * 	public static final IProxyTargetLocator INSTANCE = new UserServiceLocator(); *  * 	Object locateProxyObject() * 	{ * 		MyApplication app = (MyApplication)Application.get(); * 		return app.getUserService(); * 	} * } *  * class UserDetachableModel extends LoadableModel * { * 	private UserService svc; *  * 	private long userId; *  * 	public UserDetachableModel(long userId, UserService svc) * 	{ * 		this.userId = userId; * 		this.svc = svc; * 	} *  * 	public Object load() * 	{ * 		return svc.loadUser(userId); * 	} * } *  * UserService service = LazyInitProxyFactory.createProxy(UserService.class, * 	UserServiceLocator.INSTANCE); *  * UserDetachableModel model = new UserDetachableModel(10, service); *  * </pre> *  * The detachable model in the example above follows to good citizen pattern and is easy to unit * test. These are the advantages gained through the use of the lazy init proxies. *  * @author Igor Vaynberg (ivaynberg) *  */public class LazyInitProxyFactory{	/**	 * Primitive java types and their object wrappers	 */	private static final List PRIMITIVES = Arrays.asList(new Class[] { String.class, byte.class,			Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class,			float.class, Float.class, double.class, Double.class, char.class, Character.class,			boolean.class, Boolean.class });	/**	 * Create a lazy init proxy for the specified type. The target object will be located using the	 * provided locator upon first method invocation.	 * 	 * @param type	 *            type that proxy will represent	 * 	 * @param locator	 *            object locator that will locate the object the proxy represents	 * 	 * @return lazily initializable proxy	 */	public static Object createProxy(Class type, IProxyTargetLocator locator)	{		if (PRIMITIVES.contains(type))		{			// We special-case primitives as sometimes people use these as			// SpringBeans (WICKET-603, WICKET-906). Go figure.			return locator.locateProxyTarget();		}		else if (type.isInterface())		{			JdkHandler handler = new JdkHandler(type, locator);			try			{				return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),					new Class[] { type, Serializable.class, ILazyInitProxy.class,							IWriteReplace.class }, handler);			}			catch (IllegalArgumentException e)			{				/*				 * STW: In some clustering environments it appears the context classloader fails to				 * load the proxied interface (currently seen in BEA WLS 9.x clusters). If this				 * happens, we can try and fall back to the classloader (current) that actually				 * loaded this class.				 */				return Proxy.newProxyInstance(LazyInitProxyFactory.class.getClassLoader(),					new Class[] { type, Serializable.class, ILazyInitProxy.class,							IWriteReplace.class }, handler);			}		}		else		{			CGLibInterceptor handler = new CGLibInterceptor(type, locator);			Enhancer e = new Enhancer();			e.setInterfaces(new Class[] { Serializable.class, ILazyInitProxy.class,					IWriteReplace.class });			e.setSuperclass(type);			e.setCallback(handler);			e.setNamingPolicy(new DefaultNamingPolicy()			{				public String getClassName(final String prefix, final String source,					final Object key, final Predicate names)				{					return super.getClassName("WICKET_" + prefix, source, key, names);				}			});			return e.create();		}	}	/**	 * This interface is used to make the proxy forward writeReplace() call to the handler instead	 * of invoking it on itself. This allows us to serialize the replacement objet instead of the	 * proxy itself in case the proxy subclass is deserialized on a VM that does not have it	 * created.	 * 	 * @see ProxyReplacement	 * 	 * @author Igor Vaynberg (ivaynberg)	 * 	 */	protected static interface IWriteReplace	{		/**		 * write replace method as defined by Serializable		 * 		 * @return object that will replace this object in serialized state		 * @throws ObjectStreamException		 */		Object writeReplace() throws ObjectStreamException;	}	/**	 * Object that replaces the proxy when it is serialized. Upon deserialization this object will	 * create a new proxy with the same locator.	 * 	 * @author Igor Vaynberg (ivaynberg)	 * 	 */	static class ProxyReplacement implements IClusterable	{		private static final long serialVersionUID = 1L;		private final IProxyTargetLocator locator;		private final String type;		/**		 * Constructor		 * 		 * @param type		 * @param locator		 */		public ProxyReplacement(String type, IProxyTargetLocator locator)		{			this.type = type;			this.locator = locator;		}		private Object readResolve() throws ObjectStreamException		{			Class clazz;			try			{				clazz = Class.forName(type);			}			catch (ClassNotFoundException e)			{				throw new InvalidClassException(type, "could not resolve class [" + type +					"] when deserializing proxy");			}			return LazyInitProxyFactory.createProxy(clazz, locator);		}	}	/**	 * Method interceptor for proxies representing concrete object not backed by an interface. These	 * proxies are representing by cglib proxies.	 * 	 * @author Igor Vaynberg (ivaynberg)	 * 	 */	private static class CGLibInterceptor		implements			MethodInterceptor,			ILazyInitProxy,			Serializable,			IWriteReplace	{		private static final long serialVersionUID = 1L;		private final IProxyTargetLocator locator;		private final String typeName;		private transient Object target;		/**		 * Constructor		 * 		 * @param type		 *            class of the object this proxy was created for		 * 		 * @param locator		 *            object locator used to locate the object this proxy represents		 */		public CGLibInterceptor(Class type, IProxyTargetLocator locator)		{			super();			typeName = type.getName();			this.locator = locator;		}		/**		 * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object,		 *      java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy)		 */		public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy)			throws Throwable		{			if (isFinalizeMethod(method))			{				// swallow finalize call				return null;			}			else if (isEqualsMethod(method))			{				return (equals(args[0])) ? Boolean.TRUE : Boolean.FALSE;			}			else if (isHashCodeMethod(method))			{				return new Integer(hashCode());			}			else if (isToStringMethod(method))			{				return toString();			}			else if (isWriteReplaceMethod(method))			{				return writeReplace();			}			else if (method.getDeclaringClass().equals(ILazyInitProxy.class))			{				return getObjectLocator();			}			if (target == null)			{				target = locator.locateProxyTarget();			}			return proxy.invoke(target, args);		}		/**		 * @see org.apache.wicket.proxy.ILazyInitProxy#getObjectLocator()		 */		public IProxyTargetLocator getObjectLocator()		{			return locator;		}		/**		 * @see org.apache.wicket.proxy.LazyInitProxyFactory.IWriteReplace#writeReplace()		 */		public Object writeReplace() throws ObjectStreamException		{			return new ProxyReplacement(typeName, locator);		}	}	/**	 * Invocation handler for proxies representing interface based object. For interface backed	 * objects dynamic jdk proxies are used.	 * 	 * @author Igor Vaynberg (ivaynberg)	 * 	 */	private static class JdkHandler		implements			InvocationHandler,			ILazyInitProxy,			Serializable,			IWriteReplace	{		private static final long serialVersionUID = 1L;		private final IProxyTargetLocator locator;		private final String typeName;		private transient Object target;		/**		 * Constructor		 * 		 * @param type		 *            class of object this handler will represent		 * 		 * @param locator		 *            object locator used to locate the object this proxy represents		 */		public JdkHandler(Class type, IProxyTargetLocator locator)		{			super();			this.locator = locator;			typeName = type.getName();		}		/**		 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,		 *      java.lang.reflect.Method, java.lang.Object[])		 */		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable		{			if (isFinalizeMethod(method))			{				// swallow finalize call				return null;			}			else if (isEqualsMethod(method))			{				return (equals(args[0])) ? Boolean.TRUE : Boolean.FALSE;			}			else if (isHashCodeMethod(method))			{				return new Integer(hashCode());			}			else if (isToStringMethod(method))			{				return toString();			}			else if (method.getDeclaringClass().equals(ILazyInitProxy.class))			{				return getObjectLocator();			}			else if (isWriteReplaceMethod(method))			{				return writeReplace();			}			if (target == null)			{				target = locator.locateProxyTarget();			}			try			{				return method.invoke(target, args);			}			catch (InvocationTargetException e)			{				throw e.getTargetException();			}		}		/**		 * @see org.apache.wicket.proxy.ILazyInitProxy#getObjectLocator()		 */		public IProxyTargetLocator getObjectLocator()		{			return locator;		}		/**		 * @see org.apache.wicket.proxy.LazyInitProxyFactory.IWriteReplace#writeReplace()		 */		public Object writeReplace() throws ObjectStreamException		{			return new ProxyReplacement(typeName, locator);		}	}	/**	 * Checks if the method is derived from Object.equals()	 * 	 * @param method	 *            method being tested	 * @return true if the method is derived from Object.equals(), false otherwise	 */	protected static boolean isEqualsMethod(Method method)	{		return method.getReturnType() == boolean.class && method.getParameterTypes().length == 1 &&			method.getParameterTypes()[0] == Object.class && method.getName().equals("equals");	}	/**	 * Checks if the method is derived from Object.hashCode()	 * 	 * @param method	 *            method being tested	 * @return true if the method is defined from Object.hashCode(), false otherwise	 */	protected static boolean isHashCodeMethod(Method method)	{		return method.getReturnType() == int.class && method.getParameterTypes().length == 0 &&			method.getName().equals("hashCode");	}	/**	 * Checks if the method is derived from Object.toString()	 * 	 * @param method	 *            method being tested	 * @return true if the method is defined from Object.toString(), false otherwise	 */	protected static boolean isToStringMethod(Method method)	{		return method.getReturnType() == String.class && method.getParameterTypes().length == 0 &&			method.getName().equals("toString");	}	/**	 * Checks if the method is derived from Object.finalize()	 * 	 * @param method	 *            method being tested	 * @return true if the method is defined from Object.finalize(), false otherwise	 */	protected static boolean isFinalizeMethod(Method method)	{		return method.getReturnType() == void.class && method.getParameterTypes().length == 0 &&			method.getName().equals("finalize");	}	/**	 * Checks if the method is the writeReplace method	 * 	 * @param method	 *            method being tested	 * @return true if the method is the writeReplace method, false otherwise	 */	protected static boolean isWriteReplaceMethod(Method method)	{		return method.getReturnType() == Object.class && method.getParameterTypes().length == 0 &&			method.getName().equals("writeReplace");	}}

⌨️ 快捷键说明

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