代理模式(静态代理和动态代理)
代理模式:我觉得就是类似于Spring AOP,在不改变原有类的情况下,给某个方法的调用加一些条件。
代理总结(一):就是利用共同实现一个接口,如下例子,租房的人和中介都实现了一个接口,所以它们都有接口IRent中的rent方法,在中介Medium类中定义共同接口类型的字段private IRent rent;然后再构建一个构造器添加一个IRent类型的形参传参入口(IRent rent)
调用方法的时候,先new出租房人的对象实例IRent target = new Gerry();,命名为target,这个target实现了IRent接口,所以它就是 IRent类型的target,它就可以作为参数传给new Medium(IRent rent) 中的rent(target)。
IRent proxy = new Medium(target); 然后prox.rentHouse(); 这里调用的是接口中IRent中的rentHouse();但是因为多态,会调用创建实例的时候子类(接口的实现类)中自己重写的方法,这里proxy(Medium的实例).rentHouse();调用的是Medium中介类中的方法,而中介中的rentHouse方法里的语句是rent.rentHouse();这里的rent就是上面构造器中this.rent = rent(target)传参后的target,就是Gerry的对象实例,所以就又调用Gerry中的rentHouse();了,总而实现了代理效果。在中介Medium类的rentHouse();方法中rent.rentHouse();方法执行前可以添加任意认证要求,这种功能就像是springAOP中的功能一样不是么。
总之【核心是多态我觉得】:就是必须的实现同一个接口,这样才可以有IRent target = new Gerry();这种形式,从而有IRent proxy = new Medium(target);→proxy.rentHouse(); (rent(this.rent = rent(target).renHouse(); ) → target.rentHouse();
说了这么多都把自己说晕了感觉...看来还是没理解透彻,
代理总结(二):第二个(动态代理)我觉得换汤不换药,就是动态生成代理对象而已(利用传参把请求方的实现的所有接口组成的数组传进来,然后底层让"中介"实现它们,这样就又达到了使它们实现同一个借口的目的,从而又回到了静态代理的板子。)
一、静态代理(租房子):
gerry需要租房子,中介帮他找房子,双方都得实现一个协议-IRent接口
中介类中找到需要租房子的人,IRent rent;通过构造函数把传进来的租房人给rent,再用rent调用方法
1 package deep.staticc.demo;
2
3 public interface IRent {
4
5 public void rentHouse(String name);
6 }
1 package deep.staticc.demo;
2
3
4
5 /**
6 * 场景:gerry工作非常忙,没有时间找房子,需要找一个中介帮忙
7 * @author DeepSleeping
8 *
9 */
10 public class Gerry implements IRent{
11
12 @Override
13 public void rentHouse(String name){
14 System.out.println(name + "需要租房子");
15 }
16 }
1 package deep.staticc.demo;
2
3 public class Medium implements IRent {
4
5 //持有目标代理类的引用
6 private IRent rent;
7
8 public Medium(IRent rent){
9 this.rent = rent;
10 }
11
12
13 @Override
14 public void rentHouse(String name) {
15 rent.rentHouse(name);
16 }
17
18 }
1 package deep.staticc.demo;
2
3 public class TestProxy {
4 public static void main(String[] args) {
5 //创建目标对象
6 IRent target = new Gerry();
7 //创建一个代理对象
8 IRent proxy = new Medium(target);
9 //通过代理调用方法
10 proxy.rentHouse("gerry");
11 }
12 }
静态代理总结:局限性太大,只有共同实现了某一个接口才能够代理,即都实现了IRent接口通过多态来运转。
二、动态代理(添加信息前进行权限认证)
1 package deep.dynamic.demo;
2
3 public interface IUserDao {
4
5 void add();
6
7 void deletd();
8
9 }
1 package deep.dynamic.demo;
2
3 /**
4 * 实现认证操作功能:
5 * 项目中每一个方法的调用都需要进行4个认证
6 * 1、是否合法
7 * 2、是否有新增权限
8 * 3、开启事务
9 * 4、关闭事务
10 * @author DeepSleeping
11 *
12 */
13 public class UserDaoImpl implements IUserDao {
14
15 @Override
16 public void add(){
17 System.out.println("新增信息");
18 }
19
20 @Override
21 public void deletd() {
22 System.out.println("删除信息");
23
24 }
25 }
1 package deep.dynamic.demo.proxy;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6
7 /**
8 * 动态代理类
9 * @author DeepSleeping
10 *
11 */
12 public class ProxyClass {
13 //目标对象
14 private Object target;
15
16 public ProxyClass(Object target){
17 this.target = target;
18 }
19
20 /**
21 * 创建当前目标对象代理对象
22 * @return
23 */
24 public Object createProxy(){
25 /**
26 * loader:目标对象的类加载器
27 * interfaces:目标对象实现的所有接口组成的数组
28 * handler:定义一个调用目标类中方法的回调类
29 */
30 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
31 new InvocationHandler() {
32
33 @Override
34 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
35 //进行调用前的认证
36 System.out.println("1、是否合法");
37 System.out.println("2、是否有权限");
38 System.out.println("3、开启事务");
39 Object obj = null;
40
41
42 try {
43 method.invoke(target, args);
44
45 } catch (Exception e) {
46 System.out.println("4、关闭事务");
47 }
48 System.out.println("--业务执行正常--");
49
50 return obj;
51 }
52 });
53 }
54 }
1 package deep.dynamic.demo;
2
3 import deep.dynamic.demo.proxy.ProxyClass;
4
5 public class TestDynamicProxy {
6
7 public static void main(String[] args) {
8 //创建目标对象
9 IUserDao target = new UserDaoImpl();
10 //创建代理类的实例
11 ProxyClass proxy = new ProxyClass(target);
12 //生成对应的代理对象
13 IUserDao userDao = (IUserDao) proxy.createProxy();
14 userDao.add();
15 userDao.deletd();
16 }
17 }
附加:为什么可以强转IUserDao userDao = (IUserDao) proxy.createProxy();
是因为Proxy.newProxyInstance方法的第二个参数取得了目标对象的所有实现的接口的数组,代理对象就会实现这组接口,所以我们就可以将代理对象任意强转成这组接口的任意一个。
静态代理:共同实现一个接口,通过多态调用
动态代理:动态地实现同一个接口(通过方法传目标对象实现过的接口,然后底层自动实现它们,这样就像静态代理那样,目标和代理对象都实现了同一个接口)然后又可以利用多态强转后调用