目录
3、代理类工厂(通过静态方法传入’被代理类对象(obj)‘获取‘代理对象(proxy)’)
1、创建抽象类,对InvocationHandler 接口进行扩展(为的是解决obj的传入)
一、jdk动态代理经典实现
1、被代理类实现的接口
interface Human{
//获取信仰
String getBelif();
//吃东西
void eatFood(String foodName);
}
2、被代理类(实现接口,重写方法)
class Superman implements Human{
//获取信仰
@Override
public String getBelif() {
return "I belive that i can fly";
}
//吃东西
@Override
public void eatFood(String foodName) {
//打印
System.out.println("Superman is eating :" + foodName);
}
}
3、代理类工厂(通过静态方法传入’被代理类对象(obj)‘获取‘代理对象(proxy)’)
class ProxyFactor{
//静态方法获取代理对象
public static Object getProxyInstance(Object obj){
//创建InvocationHandler接口实现类对象
Case01Handler case01Handler = new Case01Handler(obj);
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(), //类加载器
obj.getClass().getInterfaces(), //接口列表
case01Handler //handler
);
}
}
4、创建InvocationHandler接口实现类
class Case01Handler implements InvocationHandler{
private Object obj;
//通过构造器注入obj对象
public Case01Handler(Object obj) {
this.obj = obj;
}
//代理后将被调用的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("AOP(Case01Handler): 前");
Object invoke = method.invoke(obj, args);
System.out.println("AOP(Case01Handler): 后");
return invoke;
}
}
5、测试
public class DynamicProxyTest {
public static void main(String[] args) {
//创建被代理类对象
Superman superman = new Superman();
//获取代理对象
Human supermanProx = (Human) ProxyFactor.getProxyInstance(superman);
//方法1测试
String belif = supermanProx.getBelif();
System.out.println("belif = " + belif + "\n");
//方法2测试
supermanProx.eatFood("四川火锅");
}
}
6、结果
二、handler动态化
我们观察到,以上代理工厂的实现依赖于InvocationHandler类的实现类,
那么,此代理工厂的代码结构即意味着:一个类型的代理工厂(ProxyFactor)只能对应一种aop处理方式的handler。
这种结构在实际应用中当然没有争议,但是,如果我们想要实现代理工厂与handler实现的”一对多“,或者说实现handler的动态化,可以对代理工厂代码进行如下改动:
class ProxyFactor{
//通过参数传入handler对象
public static Object getProxyInstance(Object obj, InvocationHandler handler){
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
handler
);
}
}
然后,我们可以有不同的方式传入hadler:
1)经典地,根据被代理对象(obj)构造InvocationHandler 实现类对象,传入代理工厂获取代理对象,这里就不作演示了
2)在测试类中通过匿名内部类,或者lambda表达式动态传入hadler到代理工厂,获取代理,这里演示lambda获取:
private static void test01() {
//被代理对象
Superman superman = new Superman();
//获取代理
Human supermanProx = (Human) ProxyFactor.getProxyInstance(
superman,
//lambda表达式
(Object proxy, Method method, Object[] args) -> {
System.out.println("AOP(Case01Handler): 前");
Object invoke = method.invoke(superman, args);
System.out.println("AOP(Case01Handler): 后");
return invoke;
}
);
//方法1测试
String belif = supermanProx.getBelif();
System.out.println("belif = " + belif + "\n");
//方法2测试
supermanProx.eatFood("四川火锅");
}
结果:
三、参数列表再简化
如果大家觉得即传被代理对象,又传hadler实现很麻烦,这里还可以再简化api参数列表:
1、创建抽象类,对InvocationHandler 接口进行扩展(为的是解决obj的传入)
//接口扩展
abstract class NewHandler implements InvocationHandler {
private Object obj;
public NewHandler(Object obj) {
this.obj = obj;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
2、代理工厂静态方法改造
class ProxyFactor{
//只需传入handler
public static Object getProxyInstance(NewHandler handler){
return Proxy.newProxyInstance(
handler.getObj().getClass().getClassLoader(),
handler.getObj().getClass().getInterfaces(),
handler
);
}
}
3、测试(通过NewHandler匿名内部类方式)
private static void test06() {
//被代理对象
Superman superman = new Superman();
//获取代理
Human supermanProx = (Human) ProxyFactor.getProxyInstance(
new NewHandler(superman) {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("AOP(Case01Handler): 前");
Object invoke = method.invoke(superman, args);
System.out.println("AOP(Case01Handler): 后");
return invoke;
}
}
);
//方法1测试
String belif = supermanProx.getBelif();
System.out.println("belif = " + belif + "\n");
//方法2测试
supermanProx.eatFood("四川火锅");
}
结果:
最后,不管怎样改动,需要传入的被代理对象(obj)都没有消失,我们只是它的搬运工。