专业的解释:代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。
通俗的话讲,就是代理类和被代理类拥有/实现了相同的接口类,并且代理类中持有被代理类的实例对象,被代理类通过代理类来调用自己的方法,并且可以在调用自己方法前后做一些事情。
代理模式又分为静态代理和动态代理,静态代理需要自己编写代理类,并且一个代理类对应一个被代理类,代码繁琐冗余,这里不做多余介绍。
动态代理则是指代理类在程序运行时才被创建的代理模式,动态代理常用的有两种 JDK动态代理、 CGLib动态代理
JDK动态代理
JDK动态代理两个核心类:Proxy类 和 InvocationHandler接口 都位于java.lang.reflect包下
创建动态代理对象的步骤:
1、创建一个InvocationHandler对象(创建一个与代理对象相关联的InvocationHandler)
2、使用Proxy类的getProxyClass静态方法生成一个动态代理类
3、获得stuProxyClass 中一个带InvocationHandler参数的构造器constructor
4、通过构造器constructor来创建一个动态实例stuProxy
public interface ActionIng {
/**
* 执行动作
*/
void doAction();
}
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class StudentIng implements ActionIng {
private String name;
@Override
public void doAction() {
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("嘀嘀嘀嘀哒哒~~~~~~~");
}
System.out.println(name + "正在上课");
}
}
public class StudentInvocationHandler<T> implements InvocationHandler {
T target;
public StudentInvocationHandler(T target) {
this.target = target;
}
/**
* @param proxy 是在代理实例上调用该方法的代理实例
* @param method 是在代理实例上调用的接口方法对应的{@code method}实例。{@code Method}对象的声明类将是该方法被声明的接口,该接口可能是代理类继承该方法所通过的代理接口的超接口。
* @param args 一个对象数组,包含在代理实例上的方法调用中传递的参数值,或者如果接口方法不接受参数,则{@code null}。基本类型的参数被包装在适当的基本包装器类的实例中,例如{@code java.lang。Integer}或{@code java.lang.Boolean}。
* @return @throw Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" + method.getName() + "方法");
// 其他操作
try {
Thread.sleep(2000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return method.invoke(target, args);
}
}
public class StaticProxy {
@Test
public void testDynamicProxy() {
StudentIng studentIng = new StudentIng("宋昕冉");
InvocationHandler invocationHandler = new StudentInvocationHandler<ActionIng>(studentIng);
ActionIng proxyInstance = (ActionIng) Proxy.newProxyInstance(ActionIng.class.getClassLoader(), new Class<?>[]{ActionIng.class}, invocationHandler);
proxyInstance.doAction();
}
}
JDK1.8 Proxy中的newProxyInstance()方法
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
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;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
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);
}
}
标签:代理,接口,InvocationHandler,模式,new,动态,public From: https://www.cnblogs.com/kris-cbl/p/18359723JDK动态代理为什么只能代理接口,因为生成的代理类$Proxy0 extends Proxy implements 代理接口,代理类继承了Proxy类,Java的继承机制(单继承)注定了JDK动态代理只能代理接口。