package java.lang.reflect;
public class Proxy implements java.io.Serializable {
/**
* Returns an instance of a proxy class for the specified interfaces 返回指定接口的代理类的实例,该实例将方法调用分派到指定的调用处理程序。
* that dispatches method invocations to the specified invocation
* handler.
*
*
{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
* {@code Proxy.getProxyClass} does.
*
* @param loader the class loader to define the proxy class @param loader类加载器,用于定义代理类
* @param interfaces the list of interfaces for the proxy class @param interfaces代理类要实现的接口列表
* to implement
* @param h the invocation handler to dispatch method invocations to @param h调用处理程序,以分派方法调用以使用指定类加载器定义并实现指定接口的代理类的指定调用处理程序来返回代理实例。
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
* @throws IllegalArgumentException if any of the restrictions on the @throws IllegalArgumentException,如果对可能传递给{@code getProxyClass}的参数被违反
* parameters that may be passed to {@code getProxyClass}
* are violated
* @throws SecurityException if a security manager, s, is present 如果存在安全管理器 s em>并且满足以下任何条件,则@throws SecurityException:
* and any of the following conditions is met:
*
*
the given {@code loader} is {@code null} and 给定的{@code loader}为{@code null},而调用者的类加载器不是{@code null},并使用{@code RuntimePermission(“ getClassLoader”)调用
* the caller's class loader is not {@code null} and the {@link SecurityManager#checkPermission s.checkPermission} “)}权限拒绝访问;
* invocation of {@link SecurityManager#checkPermission
* s.checkPermission} with
* {@code RuntimePermission("getClassLoader")} permission
* denies access;
*
for each proxy interface, {@code intf}, 对于每个代理接口{@code intf},调用者的类加载器与{@code intf}和调用{@link SecurityManager#checkPackageAccess
* the caller's class loader is not the same as or an s.checkPackageAccess()的类加载器都不相同或不相同}拒绝访问{@code intf};
* ancestor of the class loader for {@code intf} and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to {@code intf};
*
any of the given proxy interfaces is non-public and the 任何给定的代理接口都是非公共的,并且调用方类与非公共接口不在同一个{@linkplain软件包运行时软件包}中,并且使用以下命令调用{@link
* caller class is not in the same {@linkplain Package runtime package} SecurityManager#checkPermission s.checkPermission} {@code ReflectPermission(“ newProxyInPackage。{package name}”)}权
* as the non-public interface and the invocation of 限拒绝访问。
* {@link SecurityManager#checkPermission s.checkPermission} with
* {@code ReflectPermission("newProxyInPackage.{package name}")}
* permission denies access.
*
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
* {@code null}
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//判断InvocationHandler是否为空,若为空,抛出空指针异常
Objects.requireNonNull(h);
final Class>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.查找或生成指定的代理类对象
*/
Class> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.用指定的调用处理程序调用其构造函数
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//如果Class作用域为私有,通过反射 setAccessible 支持访问
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//获取Proxy Class构造函数,创建Proxy代理实例。
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
Proxy.getProxyClass0
利用getProxyClass0(loader, intfs)生成代理类Proxy的Class对象
package java.lang.reflect;
public class Proxy implements java.io.Serializable {
/**
* a cache of proxy classes 在此初始化WeakCache
*/
private static final WeakCache[], Class>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* Generate a proxy class. Must call the checkProxyAccess method 生成代理类。 在调用此方法之前,必须调用checkProxyAccess方法执行权限检查。
* to perform permission checks before calling this.
*/
private static Class> getProxyClass0(ClassLoader loader,
Class>... interfaces) {
if (interfaces.length > 65535) {
//如果接口数量大于65535,抛出非法参数错误
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
//如果存在由实现了给定接口的给定加载器定义的代理类,则将仅返回缓存的副本;否则,它将通过ProxyClassFactory创建代理类。
return proxyClassCache.get(loader, interfaces);
}
package java.lang.reflect;
final class WeakCache {
/**
* Look-up the value through the cache. This always evaluates the 通过缓存查找值。如果缓存中没有给定的条目或者实体已经被清除,这总是评估{@code subKeyFactory}函数,并有选择地评估{@code valueFactory}函数
* {@code subKeyFactory} function and optionally evaluates
* {@code valueFactory} function if there is no entry in the cache for given
* pair of (key, subKey) or the entry has already been cleared.
*
* @param key possibly null key @param键可能为空键
* @param parameter parameter used together with key to create sub-key and
* value (should not be null)
* @return the cached value (never null)
* @throws NullPointerException if {@code parameter} passed in or
* {@code sub-key} calculated by
* {@code subKeyFactory} or {@code value}
* calculated by {@code valueFactory} is null.
*/
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
// 懒加载 为特定的cacheKey设置第二级valuesMap
ConcurrentMap
WeakCache.Factory
package java.lang.reflect;
final class WeakCache {
/**
* A factory {@link Supplier} that implements the lazy synchronized 工厂{@link Supplier}实现了值的惰性同步构造并将其安装到缓存中。
* construction of the value and installment of it into the cache.
*/
private final class Factory implements Supplier {
private final K key;
private final P parameter;
private final Object subKey;
private final ConcurrentMap> valuesMap;
Factory(K key, P parameter, Object subKey,
ConcurrentMap> valuesMap) {
this.key = key;
this.parameter = parameter;
this.subKey = subKey;
this.valuesMap = valuesMap;
}
@Override
public synchronized V get() { // serialize access
// re-check
Supplier supplier = valuesMap.get(subKey);
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try {
//调用Proxy类中静态内部类ProxyClassFactory的apply创建代理类 valueFactory此时是Proxy.ProxyClassFactory
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue cacheValue = new CacheValue<>(value);
// try replacing us with CacheValue (this should always succeed)
if (valuesMap.replace(subKey, this, cacheValue)) {
// put also in reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}
Proxy.ProxyClassFactory
package java.lang.reflect;
public class Proxy implements java.io.Serializable {
/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/
private static final class ProxyClassFactory
implements BiFunction[], Class>>
{
// prefix for all proxy class names
// 代理类前缀
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
// 生成代理类名称的计数器,原子性,包证多线程情况可用
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class> apply(ClassLoader loader, Class>[] interfaces) {
Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
* 校验类加载器是否能通过接口名称加载该类
*/
Class> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
* 校验该类是否是接口类型 JAVA是单继承的,代理类已经继承了Proxy类了,不能再继承其他的类
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
* 校验接口是否重复
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in 代理类包名
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the 记录非公共代理接口的程序包,以便在同一包中定义代理类。 验证所有非公共代理接口都在同一包中。
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
// public代理接口,使用com.sun.proxy包名
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate. 为代理类生成名字
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class. 真正生成代理类的字节码文件的地方
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// 使用类加载器将代理类的字节码文件加载到JVM中
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the 这里的ClassFormatError表示(排除代理类生成代码中的错误)提供给代理类创建的参数还有其他一些无效方面(例如,超出了虚拟机限制)
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
//用户和本地C代码进行互操作的API,称为Java Native Interface (Java本地接口)
private static native Class> defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);
androi中提到了布尔数组;
布尔数组默认的是false, 并且只会打印false或者是true
布尔数组的例子; 根据字符数组创建布尔数组
char[] c = {'p','u','b','l','i','c'};
//根据字符数组的长度创建布尔数组的个数
boolean[] b = new bool
文章摘自:http://blog.csdn.net/yangwawa19870921/article/details/7553181
在编写HQL时,可能会出现这种代码:
select a.name,b.age from TableA a left join TableB b on a.id=b.id
如果这是HQL,那么这段代码就是错误的,因为HQL不支持
1. 简单的for循环
public static void main(String[] args) {
for (int i = 1, y = i + 10; i < 5 && y < 12; i++, y = i * 2) {
System.err.println("i=" + i + " y="
异常信息本地化
Spring Security支持将展现给终端用户看的异常信息本地化,这些信息包括认证失败、访问被拒绝等。而对于展现给开发者看的异常信息和日志信息(如配置错误)则是不能够进行本地化的,它们是以英文硬编码在Spring Security的代码中的。在Spring-Security-core-x
近来工作中遇到这样的两个需求
1. 给个Date对象,找出该时间所在月的第一天和最后一天
2. 给个Date对象,找出该时间所在周的第一天和最后一天
需求1中的找月第一天很简单,我记得api中有setDate方法可以使用
使用setDate方法前,先看看getDate
var date = new Date();
console.log(date);
// Sat J
MyBatis的update元素的用法与insert元素基本相同,因此本篇不打算重复了。本篇仅记录批量update操作的
sql语句,懂得SQL语句,那么MyBatis部分的操作就简单了。 注意:下列批量更新语句都是作为一个事务整体执行,要不全部成功,要不全部回滚。
MSSQL的SQL语句
WITH R AS(
SELECT 'John' as name, 18 as