一、静态代理
/**
* @Description 代理模式 将要代理对象的接口包装进来,在相同的方法处理中加入其他操作且不影响原先业务
* @Date 2021-02-16 13:53
*/
//接口
interface Interface{
void doSomething();
void somethingElse(String arg);
}
//实际对象
class RealObject implements Interface{
@Override
public void doSomething() {
System.out.println("real doSomething");
}
@Override
public void somethingElse(String arg) {
System.out.println("real somethingElse "+arg);
}
}
//代理器继承相同的接口,且把接口装进来(为了装实际对象)
class SimpleProxy implements Interface{
private Interface proxied;
public SimpleProxy(Interface proxied){ //通过构造器把接口包装进来
this.proxied = proxied;
}
@Override
public void doSomething() { //在不影响原业务逻辑的情况下,相同方法中进行更多操作
//执行前
System.out.println("SimpleProxy dosomething");
//实际对象方法
proxied.doSomething();
//执行后
System.out.println("SimpleProxy dosomething after");
}
@Override
public void somethingElse(String arg) { //在不影响原业务逻辑的情况下,相同方法中进行更多操作
//执行前
System.out.println("SimpleProxy somethingElse "+arg);
//实际对象方法
proxied.somethingElse(arg);
//执行后
System.out.println("SimpleProxy somethingElse after");
}
}
public class SimpleProxyDemo {
//consumer方法接收Interface对象,RealObject和SimpleProxy都实现了该接口(多态),所以都可以接收
public static void consumer(Interface iface){
//分别执行两个方法
iface.doSomething();
iface.somethingElse("biu biu");
}
public static void main(String[] args) {
consumer(new RealObject());//普通调用
System.out.println(" ====== ");
consumer(new SimpleProxy(new RealObject()));//代理调用
}
}
个人简单理解:代理类,就是自己包含目标类(把它作为自己的属性,这跟子类继承父类不同),继承的是和目标类相同的接口,所以实现了相同的方法,在相同的方法中触发相应的目标方法(这里有点像子类super()),在方法中增加自定义的额外处理。
二、java动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Description 动态代理
* @Date 2021-02-08 15:47
*/
//SimpleProxyDemo类中已有
//interface Interface{
// void doSomething();
// void somethingElse(String arg);
//}
//class RealObject implements Interface{
//
// @Override
// public void doSomething() {
// System.out.println("real doSomething");
// }
//
// @Override
// public void somethingElse(String arg) {
// System.out.println("real somethingElse "+arg);
// }
//}
class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("*** proxy: " + proxy.getClass() + ", method: " + method + ", args: " + args);
if (args != null) {
for (Object arg : args) {
System.out.println(" " + arg);
}
}
//可以对method直接进行判断需不需要执行 return null
return method.invoke(proxied, args); //注意是proxied,不是传入的proxy
//可以在invoke前和后做其他想做的事 写法稍做修改
//sout();
// obj = invoke();
//sout();
// return obj;
}
}
public class SimpleDynamicProxy {
public static void consumer(Interface iface) {
iface.doSomething();
iface.somethingElse("biu biu");
}
public static void main(String[] args) {
RealObject real = new RealObject();
consumer(real);//普通调用
System.out.println(" ============== ");
//newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
// 三个参数分别是类加载器, 代理实现的接口数组, InvocationHandler的一个具体实现
Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(),
new Class[]{Interface.class}, new DynamicProxyHandler(real));
consumer(proxy);//动态代理调用
}
}
请注意 method.invoke使用的是自己的proxied。
动态代理组装:
1、一个目标对象,目标对象继承的接口
2、一个handler对象 继承 InvocationHandler,将目标对象通过构造器包进去
3、通过Proxy.newProxyInstance()创建动态代理,动态代理可以将所有调用重定向到调用处理器(handler对象),newProxyInstance会通过反射去找目标对象继承的接口列表,通过反射执行接口的方法。
spring aop有两种模式一种jdk动态代理(默认),另一种cglib动态代理(类没有接口)
个人感受:静态代理是有一个代理类,直接在代理方法中写好处理逻辑;动态代理则是Proxy和InvocationHandler,执行靠反射,通过继承接口找到方法,通过invoke执行。两者都是面向接口的