1:动态代理
1:自我看法
什么是动态代理,简单的讲就是让别人帮你做事情。同时别人在做的时候,顺便可以做的其他事情,而这些事情就是加强,因为自己没法做。
2:例子
举个例子,小明是班长,小红是小明的同班同学,新学期到了,每个人都要交班费,(当然小明和小红都要交),显然”交班费“这是他们共有的方法,由于小红当天没有带钱,第二天又不想单独去交,所以交给小明,此时,小明就是成为了小红的交钱的代理者(拿到小红的钱,帮她交钱),路上小明看见了自己暗恋的小芳,主动上前告白(我们视为“告白”,是小明的一个方法,显然小红相对于小明没有),告白完之后,就去交钱了。 从上面这个过程中我可以知道: 小明干了两件事1:帮小红交钱,2:告白 小红做了一件事1:交钱
3:总结
从上面我们知道,小明帮小红做事,小明是需要小红的一些东西的,除此之外,小红的身份是可以变换的,可以是小芳,也可以是小兰,所以此时,小明就相当于工厂,小红,小兰,小芳相当工厂中的货物。因此,在我们进行代理时,只需要将方法参数进行变化就可以实现对不同类的代理。
2:动态代理的分类
动态代理分为jdk动态代理与cglib代理。 jdk代理:由java的反射机制实现,被代理的类必须至少实现一个接口,否则无法被代理 cglib代理:通过地层的asm实现,可以代理实现接口的类,也可以代理不实现接口的类,但该类不能被final修饰。
3:动态代理的使用
当我们写了一个类时,觉得他当前的功能不太全面,但这个类当前无法更改,我们又要有一些新的功能,如方法前后查看日志等等。就可以使用代理对方法进行加强,即使用该方法时我们又查看了日志等情况。
JDK动态代理
1:使用代理工厂进行实现
1.1:主要方法的参数
@创建代理对象的类。 @代理方式:基于实现接口的类的动态代理 @涉及类:Proxy @提供方:JDK @创建代理对象涉及方法:newProxyInstance()-----创建代理对象的方法 该方法是Proxy类中的静态方法(静态方法:不需要创建类,直接 类.方法即可)
参数1:
classLoader:类加载器(XX.getClass().getClassLoader)
用于加载代理对象的字节码(代理对象和被代理对象使用相同的类加载器)
参数2:
class[]:
用于使代理对象和被代理对象有相同的方法
参数3:
InvocationHandler:
一般写该接口的实现类(但当前ProxyFactory不是实现其实现类,
本类是工厂模式)自己创建一个实现InvocationHandler接口的类,
该类实际上是一个 “中介类”,用来写增强代码
@要求:被代理类(目标对象)必须实现一个接口
1.2:被代理类实现的接口
public interface ImProducer {
public void before();
public void after() ;
}
1.3:被代理类
public class Producer implements ImProducer{
public void before(){
System.out.println("before");
}
public void after() {
System.out.println("after");
}
}
1.4:代理工厂(产生代理对象)
public class ProxyFactory {
//设置一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
//返回目标对象的一个代理对象
//这个方法函数是自己写的
public Object getProxy() {
//返回的newProxyInstance这个方法函数是proxy类中的静态方法
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
/**
* 作用:执行被代理对象的所以有方法都会经过该方法
*
* @param proxy :代理对象的引用,代表动态代理对象
* @param method :当前执行的方法
* @param args :当前执行方法所需要的参数
* @return 与被代理对象方法的返回值相同
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue = null;
//方法1:
//方法2:
//......
//执行目标对象方法
returnValue = method.invoke(target,args);
//方法3:
//方法4:
//......
//以上除目标方法外的方法,都是增强方法
return returnValue;
}
});
}
}
1.5:测试
//目标对象
ImProducer target = new Producer();
//获得代理对象:参数可以是其他类,该方法为模板,只需要给对应的目标对象
ImProducer proxy = (ImProducer) new ProxyFactory(target).getProxy();//最好用接口
//jdk为我们的生成了$Proxy0的代理类,当多个代理类时$Proxy0后面数字可以增加,以此区别代理类
// 如$Proxy1,$Proxy2.。。。。。
proxy.before();
proxy.after();
1:实现InvocationHandler接口的动态代理
被代理类实现的接口和被代理类与上面工厂模式的动态代理相同。
1.1:InvocationHandler接口的实现类
public class ExtendInvocationHandler implements InvocationHandler {
//设置一个目标对象
private Object target;
public ExtendInvocationHandler(Object target){
this.target=target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 作用:执行被代理对象的所以有方法都会经过该方法
*
* @param proxy :代理对象的引用,代表动态代理对象
* @param method :当前执行的方法
* @param args :当前执行方法所需要的参数
* @return 与被代理对象方法的返回值相同
* @throws Throwable
*/
Object returnValue = null;
//方法1:
//方法2:
//......
//执行目标对象方法
returnValue = method.invoke(target,args);
//方法3:
//方法4:
//......
//以上除目标方法外的方法,都是增强方法
return returnValue;
}
}
1.2: 测试
//目标对象
ImProducer target = new Producer();
InvocationHandler handler=new ExtendInvocationHandler(target);
ImProducer proxy1 = (ImProducer)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
proxy1.before();
proxy1.after();
Cglib动态代理
由于JDK只能代理实现接口的类,而在实际开发中一些类没有代理接口但需要增强,所以cglib弥补了这一缺点,而cglib代理方式是通过“继承”被代理类,将其作为父类,然后继承被代理类的所有的公开方法,然后重写这些方法,在重写时对这些方法增强。通常情况下,要实现MethodInterceptor接口。
1.1:主要参数
@创建代理对象的子类。 @代理方式:基于子类的动态代理 @涉及类:Enhancer @提供方:cglib库 @创建代理对象涉及方法:create()-----创建代理对象的方法
参数1:
class:字节码
指定的被代理对象的字节码
参数2:
Callback:用于提供增强的代码
一般写该MethodInterceptor接口的实现类
@要求:代理的对象不是最终类,针对类来进行代理(被代理类不需要实现接口)
1.2:被代理类
public class Producer implements ImProducer{
public void before(){
System.out.println("before");
}
public void after() {
System.out.println("after");
}
}
1.3:实现MethodInterceptor
public class ProxyFactory implements MethodInterceptor{
public Object getProxy(Class cls) {
//1.创建Cglib中enhancer增强类对象
Enhancer en = new Enhancer();
//2.设置要增强的类型(被代理类也就是目标对象)
en.setSuperclass(cls);
//3.定义代理逻辑对象为当前对象(类对象),但要求当前对象实现MethodInterceptor接口
en.setCallback(this);
//生成代理对象并返回
Object proxy = en.create();
return proxy;
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object returnValue = null;
//方法1:
//方法2:
//......
//执行目标对象方法
returnValue = methodProxy.invokeSuper(proxy,args);
//方法3:
//方法4:
//......
//以上除目标方法外的方法,都是增强方法
return returnValue;
}
}
1.4:测试
ProxyFactory proxyFactory =new ProxyFactory();
Producer proxy=(Producer) proxyFactory.getProxy(Producer.class);
proxy.before();
proxy.after();