本文主要参考慕课网视频学习,在此记录一下,个人感觉讲的非常棒。随着对spring框架的了解,代理模式在其中发乎了很大作用,要想更好的理解spring的核心之一AOP需要对代理模式有一些了解。
代理模式我个人理解就是通过一个对象A去访问另外一个对象B,而不是直接去访问B,为什么不直接访问B呢?因为有时候我们需要在访问B之前做一些代码逻辑判断,比如spring框架中的面向切面编程,我需要判断用户是否登录才能访问a,b,c,d这四个函数,就可以通过切面实现,并且没有破坏a,b,c,d函数的代码,只需要在每一个函数上面加一个注解或者通过正则表达式进行判断。
静态代理静态代理: 代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类
以汽车行驶,记录汽车行驶时间为例子进行讲解,首先创建一个Movable接口。
public interface Moveable {
void move();
}
创建一个Car实现类
import java.util.Random;
/**
* Create by fengguofei
* Date: 2018/8/5
* Time: 13:39
*/
public class Car implements Moveable{
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
//实现开车
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶。。。 汽车行驶时间:" + (endtime - starttime) + "毫秒!");
}
}
创建一个测试Client类
public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move();
}
}
输出
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。 汽车行驶时间:621毫秒!
可以看到实现了汽车行驶时间的记录
通过继承实现代理
创建一个Car2继承Car,然后删除Car里面有关计时的代码,放到Car2里面。
修改Car类代码
public class Car implements Moveable{
@Override
public void move() {
// long starttime = System.currentTimeMillis();
// System.out.println("汽车开始行驶。。。");
//实现开车
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中。。。");
} catch (InterruptedException e) {
e.printStackTrace();
}
// long endtime = System.currentTimeMillis();
// System.out.println("汽车结束行驶。。。 汽车行驶时间:" + (endtime - starttime) + "毫秒!");
}
}
创建Car2
public class Car2 extends Car{
@Override
public void move(){
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
super.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶。。。 汽车行驶时间:" + (endtime - starttime) + "毫秒!");
}
}
修改Client类代码
public class Client {
public static void main(String[] args) {
// Car car = new Car();
// car.move();
Moveable m = new Car2();
m.move();
}
}
输出
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。 汽车行驶时间:906毫秒!
通过Car2里面的super.move实现了对Car的代理。
使用聚合方式
创建Car3
public class Car3 implements Moveable {
private Car car;
public Car3(Car car) {
super();
this.car = car;
}
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
car.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶。。。 汽车行驶时间:" + (endtime - starttime) + "毫秒!");;
}
}
修改Client类代码
public class Client {
public static void main(String[] args) {
// Car car = new Car();
// car.move();
//使用集成方式
// Moveable m = new Car2();
// m.move();
//使用聚合方式实现
Car car = new Car();
Moveable m = new Car3(car);
m.move();
}
}
输出
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。 汽车行驶时间:652毫秒!
聚合方式我感觉就是两个类实现同一个接口,Car类实现move功能,然后通过构造函数把Car类注入到Car3中,在调用Car类move时做一些处理,从而实现了代理功能。
继承方式和聚合方式那个好一点呢?答案是聚合方式!
如果我们需要在Move上实现时间处理、权限、日志等功能。比如需要实现先输出时间,再输出日志就需要创建一个Car4继承Car,如果我想先输出日志,再输出时间呢?就需要在创建一个Car5继承Car,只是顺序颠倒一下,就需要在创建一个,如果功能多的话,就需要创建很多类,太麻烦了。使用聚合就不会有这种问题出现。
直接上代码,看了就懂了。
创建一个时间代理类CarTimeProxy
public class CarTimeProxy implements Moveable {
private Moveable m;
public CarTimeProxy(Moveable m) {
super();
this.m = m;
}
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
m.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶。。。 汽车行驶时间:" + (endtime - starttime) + "毫秒!");;
}
}
创建一个日志代理类CarLogProxy
public class CarLogProxy implements Moveable {
private Moveable m;
public CarLogProxy(Moveable m) {
super();
this.m = m;
}
@Override
public void move() {
System.out.println("日志开始。。。");
m.move();
System.out.println("日志结束。。。");;
}
}
修改Client代码
public class Client {
public static void main(String[] args) {
// Car car = new Car();
// car.move();
//使用集成方式
// Moveable m = new Car2();
// m.move();
//使用聚合方式实现
// Car car = new Car();
// Moveable m = new Car3(car);
// m.move();
Car car = new Car();
CarTimeProxy ctp = new CarTimeProxy(car);
CarLogProxy clp = new CarLogProxy(ctp);
clp.move();
}
}
输出
日志开始。。。
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。 汽车行驶时间:843毫秒!
日志结束。。。
上面是先输出日志,再输出时间。如果我想先输出时间,再输出日志呢?
只需要修改一下顺序即可
Car car = new Car();
CarLogProxy clp = new CarLogProxy(car);
CarTimeProxy ctp = new CarTimeProxy(clp);
ctp.move();
输出
汽车开始行驶。。。
日志开始。。。
汽车行驶中。。。
日志结束。。。
汽车结束行驶。。。 汽车行驶时间:510毫秒!
在后面一篇文章进行JDK动态代理和cglib动态代理的讲解。
设计模式之代理模式二
网友评论