动态代理
1、动态代理概述
- 简单来说:拦截真是对象方法的直接访问,增强真是对象方法的功能
- 详细来说:代理类在程序运行过程中创建的代理对象称为动态代理,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。也就是说你想获取哪个对象的代理,动态代理就会动态的为你生成这个对象的代理对象。动态代理可以对被代理对象的方法进行增强,可以在不修改方法源码的情况下,增强被代理对象方法的功能,在方法执行前后做任何你想做的事情。动态代理技术都是在框架中使用居多,例如:Struts1、Struts2、Spring和Hibernate、mybatis等后期学的一些主流框架技术中都使用了动态代理技术。
2、动态代理代码演示
java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一个静态方法来为一组接口的实现类动态地生成代理类及其对象
//接口
public interface Star {
void sing();
}
//接口实现类
public class ChunGe implements Star{
//重写方法
@Override
public void sing() {
System.out.println("春哥在唱:你侬我侬!");
}
}
public class Test {
public static void main(String[] args) {
// 创建春哥对象!(被代理对象)(目标对象)
Star star = new ChunGe();
// 根据本被代理对象!创建出代理对象!(杨景旭)
/*
第一个参数:根据被代理对象获得的类加载器!(专门用于将字节码文件加载到内存生成对应的Class对象!)
【可以通过这个类型的加载器,在程序运行时,生成的代理类加载到JVM即Java虚拟机中,以便运行时需要】
第二个参数:根据被代理对象获得所有父接口!(,以便于生成的代理类可以具有代理类接口中的所有方法)
第三个参数:它是一个代理类(使用匿名内部类)
*/
Star startProxy = (Star) Proxy.newProxyInstance(star.getClass().getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() {
/**
* invoke方法:用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类方法的处理以及访问.
*
* @param proxy :就是一个代理对象!【在此处没啥卵用!】
* @param method :被代理对象的方法对象!
* @param args :被代理对象的方法对象的参数列表!
* @return :功能方法(接口的)的返回值!
* @throws Throwable :异常!
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在原有功能之前进行增强!
System.out.println("收费10000");
// 代理对象(杨景旭)不具备唱歌的能力!调用被代理对象(春哥)的方法完成!
method.invoke(star,null);
//在原有功能之后进行增强!
System.out.println("晚上一起吃个饭!");
return null;
}
});
// 坤坤调用代理对象的唱歌方法!
startProxy.sing(); // 每执行一次当前方法,它都会进入代理对象对应的类的方法invoke
}
}
3.4 动态代理小结:
- 动态代理非常的灵活,可以为任意的接口实现类对象做代理
- 动态代理可以为被代理对象的所有接口的所有方法做代理,动态代理可以在不改变方法源码的情况下,实现对方法功能的增强,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。 动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
- 动态代理同时也提高了开发效率。
- 缺点:只能针对接口的实现类做代理对象,普通类是不能做代理对象的。