假如我们有一段代码,要在这段代码前加权限,日志,过滤等操作我们该怎么办?我的第一想法就是直接在代码前写代码就好了,可是这样会使业务逻辑的代码量增大,不能使我们专注于业务逻辑的思考,并且如果我们看不到原来的代码就更加无所适从了。
下面通过代码的方式提出三种方法方便大家处理以上情况
首先定义一个接口
public interface Car {
public void running();
}其次是他的实现类
public class CarImpl implements Car{
@Override
public void running() {
//System.out.println("start");
System.out.println("the beautiful girl in the car is crying");
//System.out.println("end");
}
}然后是测试类
public static void main(String[] args) {
Car car = new CarImpl();
car.running();
}}
假如我们需要在running前后加些代码,又拿不到CarImpl源码,我们可以采用以下几种方法来解决这个问题
一:继承
我们可以再写一个实现类CarImpl2继承CarImpl即可,代码如下
public class CarImpl2 extends CarImpl{
@Override
public void running() {
System.out.println("start");
super.running();
System.out.println("end");
}
}
测试类如下
public static void main(String[] args) {
Car car = new CarImpl2();
car.running();
}这样我们就实现了在前后加代码的功能了,可是这种方法并不好,耦合性太强,父类改了,子类也不得不会做出相应变化,不灵活。并且如果还有别的实现类要增加代码,还得再继承一遍,再写一次代码。
二 :组合
相较于继承,组合具有更大的灵活性,代码如下
这里CarImpl2实现Car接口
public class CarImpl2 implements Car{
/*
* 相当于
* private Car car = new CarImpl();
**/
private Car car;
public CarImpl2(Car car){
this.car = car;
}
@Override
public void running() {
System.out.println("start");
car.running();
System.out.println("end");
}
}
测试类如下:
public static void main(String[] args) {
Car car = new CarImpl2(new CarImpl());
car.running();
}这种写法在代理模式里属于静态代理,他只能为一个类服务,仍有不方便,如果我要是想在每一个类每一个方法前都要加上一段代码,或者说有的要加有的不加,这样我们就不是很方便,如果我们能把这些东西单独拿出来,写在一个xml文件里想必是极好的,这就是 spring的AOP机制,当然今天我们不聊AOP,而是聊AOP背后的原理,动态代理。代理模式分为动态代理和静态代理,代理类对象本身并不真正实现服务,而是通过调用委托类对象的相关方法来提供服务,具体含义大家可以去网上找一下,很多,我不详述。
三:动态代理
如果不深究,动态代理其实就只要记住一个接口一个类即可,即InvovationHandler,Proxy;
这里我们写一个CarProxy类,他继承了InvovationHandler接口,如下;
public class CarProxy implements InvocationHandler {
private Object target;
public CarProxy(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("start");
method.invoke(target, args);
System.out.println("end");
return null;
}
}
测试类如下:
public static void main(String[] args) {
Car car = new CarImpl();
CarProxy carProxy = new CarProxy(car);
Car car1 = (Car)Proxy.newProxyInstance(car.getClass().getClassLoader(), car.getClass().getInterfaces(), carProxy);
car1.running();
}
以下两篇大神的文章阐释了Jdk动态代理,贴出来供大家参开
本文介绍了在Java中如何通过继承、组合以及动态代理三种方式,在不修改原有代码的情况下为方法添加额外的功能。重点讲解了动态代理的实现原理及其优势。
387

被折叠的 条评论
为什么被折叠?



