一、 动态代理模式
代理: 生成一个代理对象,来代理真实对象,从而控制真实对象的访问
1、静态代理
在编译期需要程序员通过程序自定义代理类和创建代理对象
2、动态代理
JDK动态(Dynamic)代理
javase提供了动态产生代理对象的API,JDK动态代理需要业务接口,在程序运行过程中动态产生代理对象
1、代理类完成的功能
1.目标类中方法的调用
2.功能增强
2.动态代理
在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点。
动态代理中目标类即使很多,1) 代理类数量可以很少,2) 当你修改了接口中的方法时,不会影响代理类。
**动态代理 **: 在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类。
换句话说:动态代理是一种创建java对象的能力,让你不用创建代理类,就能创建代理类对象。
在java中,要想创建对象:
1.创建类文件,java文 件编译为class
2.使用构造方法,创建类的对象。
动态代理的实现:
1、jdk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能。
反射包java. lang. reflect,里面有三个类: InvocationHandler ,Method, Proxy .
2、cglib动态代理(了解) : cglib是第三方的工具库,创建代理对象。cglib的原理是继承,cglib通过继承 目标类,创建它的子类,在子类中重写父类中同名的方法,实现功 能的修改。因为cglib是继承,重写方法,所以要求目标类不能是fina1的,方 法也不能是final的。cglik的要求目标类比较宽松,只要能继承就可以了。cglib在很多的框架中使用,比如mybatis,spring框架 中都有使用。
2、jdk动态代理:
1、反射:
Method类,表示方法。类中的方法。通 过Method可以执行某个方法。
2、jdk动态代理的实现:
反射包java. lang. reflect,里面有三个类:InvocationHandler,Method, Proxy .
3、InvocationHandler接口
( 调用处理器) :就- - 个方法invoke ( )
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法中。
代理类完成的功能
1.调用目标方法,执行目标方法的功能
2.功能增强,在目标方法调用时,增加功能。
3、方法原型
参数:
object proxy : jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对 象的
object[] args:目标类中方法的参数,jdk提供的。
public object invoke (object proxy, Method method, object[] args)
1、InvocationHandler接口
表示你的代理要干什么。
怎么用:
1、创建类实现接口InvocationHandler
2、重写invoke ( )方法,
把原来静态代理中代理类要完成的功能,写在这InvocationHandler实现类中
3、Method类:表示方法的,确切 的说就是目标类中的方法。
作用:通过Method可以执行某个目标类的方法,Method. invoke () ;
method. invoke (目标对象,方法的参数)
2、Proxy类
核心的对象,创建代理对象。之前创建对象都是new类的构造方法()
现在我们是使用Proxy类的方法,代替new的使用。
方法:静态方 法newProxyInstance ()
1、参数:
-
ClassLoader loader 类加载器,负贲向内存中加载对象的。使用 反射获取对象的ClassLoader
类a,a.getCalss () . getClassLoader(),目 标对象的类加载器 -
Class<?>[] interfaces:
接口,目标对象实现的接口,也是反射获取的。 -
InvocationHandler h :我们自己写的,用于目标对象方法增强!
public static object newProxyInstance (ClassLoader loader ,
Class<?>[] interfaces ,
InvocationHandler h)
3、案例
1、首先定义目标对象
package com.dyh.dongtai;
public interface A {
public void changGe(Sting string);
}
2、实现目标对象的方法
package com.dyh.dongtai;
public class User implements A {
@Override
public void changGe(String string) {
System.out.println(string + "唱歌!");
}
}
3、目标方法增强代码
package com.dyh.dongtai;
public class ZengQiang {
public static void qian() {
System.out.println("业务前");
}
public static void hou() {
System.out.println("业务后");
}
}
4、创建代理对象
package com.dyh.dongtai;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//实现InvocationHandler创建代理(可以用内部类实现 如下)
/*
class B implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ZengQiang.qian();
User user = new User();
Object invoke = method.invoke(user);
ZengQiang.hou();
return invoke;
}
}
*/
// 创建一个代理对象的方法
public class Daili {
public User user;
public Daili(User user) {
this.user = user;
}
/*
getClass 获取字节码文件()
getClassLoder 获取类加载器(字节码文件反射得到)
getInterfaces() 动态代理类需要实现的接口,拿到传入对象所有接口的实现类)
动态代理方法在执行时,会调用InvocationHandler实现类里面的invoke方法去执行
*/
public Object getProxy() {
//内部类实现代理对象的创建 new InvocationHandler()
return Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
ZengQiang.qian();
Object invoke = method.invoke(user, args);
ZengQiang.hou();
return invoke;
}
});
}
}
5、测试类
package com.dyh.dongtai;
public class TextUser {
public static void main(String[] args) {
//创建实现类
User user = new User();
//创建代理类,传入参数
Daili daili = new Daili(user);
//调用getProxy代理方法
A proxy = (A)daili.getProxy();
proxy.changGe("李四");
}
}
结果