/**
* 被代理对象
* Created by blacktoast on 2018/1/3.
*/
public interface ProxiedObject {
public void doSomething1();
public void doSomething2();
}
import android.util.Log;
/**
* Created by blacktoast on 2018/1/3.
*/
public class ConcreteProxiedObject implements ProxiedObject {
@Override
public void doSomething1() {
Log.e("TAG", "doSomething1");
}
@Override
public void doSomething2() {
Log.e("TAG", "doSomething2");
}
}
import android.util.Log;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* Created by blacktoast on 2018/1/3.
*/
public class ProxyHandler implements InvocationHandler {
private Object proxied;
public ProxyHandler(Object object) {
this.proxied =object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.e("TAG", "do something before proxied object invoked.");
Object invoke = method.invoke(proxied, args);
Log.e("TAG", "do something after proxied object invoked.");
return invoke;
}
}
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.example.yinhua.aoptest.dl.ConcreteProxiedObject;
import com.example.yinhua.aoptest.dl.ProxiedObject;
import com.example.yinhua.aoptest.dl.ProxyHandler;
import java.lang.reflect.Proxy;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testDyProxy();
}
public void testDyProxy() {
ConcreteProxiedObject concreteProxiedObject = new ConcreteProxiedObject();
ProxiedObject proxiedObject = (ProxiedObject) Proxy.newProxyInstance(ProxiedObject.class.getClassLoader(),
new Class[]{ProxiedObject.class},// 或者concreteProxiedObject.getClass().getInterfaces()
new ProxyHandler(concreteProxiedObject));
proxiedObject.doSomething1();
Log.e("TAG", "here:" + proxiedObject.getClass().getName());
}
}
Log信息:
E/TAG: do something before proxied object invoked.
E/TAG: doSomething1
E/TAG: do something after proxied object invoked.
E/TAG: here:$Proxy0
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
// 拷贝Interface
final Class>[] intfs = interfaces.clone();
// Android-changed: sm is always null
// final SecurityManager sm = System.getSecurityManager();
// if (sm != null) {
// checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
// }
/*
* Look up or generate the designated proxy class.
* 依据ClassLoader、Interface生成代理类对象
* ------> 如何生成代理类是关键
*/
Class> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// Android-changed: sm is always null
// if (sm != null) {
// checkNewProxyPermission(Reflection.getCallerClass(), cl);
// }
// 通过反射生成代理对象
// 反射处理代理对象构造函数
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 判断修饰符不为public时设置私有可访问
if (!Modifier.isPublic(cl.getModifiers())) {
// Android-changed: Removed AccessController.doPrivileged
cons.setAccessible(true);
}
// 生成实例
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);
}
}
getProxyClass0源码分析
Class> cl = getProxyClass0(loader, intfs);获取代理类
private static Class> getProxyClass0(ClassLoader loader,
Class>... interfaces) {
// 判断接口个数是否超出限制65535方法限制,这里不重要,哈哈哈
if (interfaces.length > 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
return proxyClassCache.get(loader, interfaces);
}
proxyClassCache分析
new KeyFactory()、new ProxyClassFactory()这两个对象处理所有代理类的映射
/**
* a cache of proxy classes
* 这是代理类的缓存管理
* 注意:new KeyFactory()、new ProxyClassFactory()这两个对象,后面分析用到
*/
private static final WeakCache[], Class>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* WeakCache.get(loader, interfaces)
*/
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// 通过key(ClassLoader)获取映射关系,即CacheKey和Factory之间的映射
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap
Factory源码分析
通过Factory生成代理对象
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 {
// 通过ValueFactory生成一个代理对象
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实现Supplier接口重写了hashcode和equals方法,好像没什么用啊,没想明白
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;
}
}
KeyFactory源码分析
private static final class KeyFactory
implements BiFunction[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class>[] interfaces) {
switch (interfaces.length) {
// 生成Key,Key有自己重载的Object方法
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
ProxyFactory(ValueFactory)源码分析
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中没有多继承
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();
// 判断interface是否public
// 不是public修饰时,生成的代理类为包名+类名$Proxy1
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 the default package.
proxyPkg = "";
}
// 这部分逻辑和java不太一样,java生成的代理类为com.sun.proxy$Proxy1,而Android中则通常则生成$Proxy1
{
// Android-changed: Generate the proxy directly instead of calling
// through to ProxyGenerator.
List methods = getMethods(interfaces);
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
validateReturnTypes(methods);
List[]> exceptions = deduplicateAndGetExceptions(methods);
Method[] methodsArray = methods.toArray(new Method[methods.size()]);
Class>[][] exceptionsArray = exceptions.toArray(new Class>[exceptions.size()][]);
/*
* Choose a name for the proxy class to generate.
*/
// $Proxy都带有一个数字,这个数字每次生成都会加1
//因为nextUniqueNumber每次都会加1,就生成不同的代理对象
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// 真正生成动态代理对象,有native层实现
return generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
}
}
动态代理代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。比如,现在存在一个UserService类:public class UserService { public void test() { System.out.println("test..."); }}此时,我们new一个UserService对象,然后执行test()方法,结果是
可是为什么再一次失败之后就变成直接跳过那个要求
enter full pathname of java.exe的界面
这个java.exe是你的Oracle 11g安装目录中例如:【F:\app\chen\product\11.2.0\dbhome_1\jdk\jre\bin】下的java.exe 。不是你的电脑安装的java jdk下的java.exe!
注意第一次,使用SQL D
一、rank()/dense_rank() over(partition by ...order by ...)
现在客户有这样一个需求,查询每个部门工资最高的雇员的信息,相信有一定oracle应用知识的同学都能写出下面的SQL语句:
select e.ename, e.job, e.sal, e.deptno
from scott.emp e,
(se
ReadTimeoutHandler的实现思路:
开启一个定时任务,如果在指定时间内没有接收到消息,则抛出ReadTimeoutException
这个异常的捕获,在开发中,交给跟在ReadTimeoutHandler后面的ChannelHandler,例如
private final ChannelHandler timeoutHandler =
new ReadTim
Chrome Web Store 安装地址: https://chrome.google.com/webstore/detail/replace-google-cdn/kpampjmfiopfpkkepbllemkibefkiice
由于众所周知的原因,只需替换一个域名就可以继续使用Google提供的前端公共库了。 同样,通过script标记引用这些资源,让网站访问速度瞬间提速吧
2.1 默认方法(default method)
java8引入了一个default medthod;
用来扩展已有的接口,在对已有接口的使用不产生任何影响的情况下,添加扩展
使用default关键字
Spring 4.2支持加载在默认方法里声明的bean
2.2
将要被声明成bean的类
public class DemoService {