掌握Java设计模式之代理设计模式(2)

原创
2018/03/29 15:19
阅读数 311

概念

      举例:我要灭了传说中的山口组,我通知青龙帮,然后青龙帮 帮我灭了,最终达到了我要灭山口组的目的,我亲自灭和别人帮我灭结果都一样的,所以,青龙帮就相当于代替了我,这种方式叫代理模式。

2、技术点(反射)

      了解下反射,可能只讲代理设计模式的话可能你不需要掌握,但是代理设计模式的应用场景会讲到,还是希望你能够了解下反射知识点。

3、代理设计模式

    3.1 静态代理

1、概念:目标对象、和代理对象统一实现一样的接口 缺点,代理类太多的情况,一旦增加接口方法,那么目标对象与代理对象都要重新修改和维护。

2、代码讲解 类:接口IUserDao、实现接口的两个类,目标类和代理类 GirlUser和ProxyGirl,最后main函数执行(java9版本以上)

      代码如下       

public interface IUserDao {

    public static final String girlName ="七七";

    void miss(String boyName);

    static void love(){
        System.out.println("恋爱");
    };

    default void noLove(){
        System.out.println("高冷,不谈恋爱");
    }

    private static void securt(){
        System.out.println("每个女孩子内心都有一个小秘密");
    }
}
public class GirlUser implements IUserDao{

    @Override
    public void miss(String boyName) {
        System.out.println("我在思念岳飞将军");
    }

    @Override
    public void noLove() {
        System.out.println("我跟谁也不谈恋爱,你们男的一个比一个丑");
    }
}
public class ProxyGirl implements IUserDao{

    private IUserDao iUserDao;

    public ProxyGirl(IUserDao iUserDao){
        this.iUserDao = iUserDao;
    }

    @Override
    public void miss(String boyName) {
        System.out.println("我告诉你们男生他在思念几百年前的岳飞大将军");
    }

    @Override
    public void noLove() {
        System.out.println("她不会和你们恋爱的,你们死心吧");
    }
}
public class Main {

    public static void main(String[] args){
        //可以做到在不修改目标对象的功能前提下,对目标功能扩展.
        //因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
        GirlUser girlUser   = new GirlUser();
        ProxyGirl proxyGirl = new ProxyGirl(girlUser);
        proxyGirl.noLove();

    }
}

        运行结果

    3.2 jdk动态代理

1、概念:jdk动态代理是代理对象类不需要实现接口!但是目标对象一定要实现接口!

2、代码实现 用到的类  IUserDao GirlUser DongtaiProxy,由于3.1.2已经写了两个类了,我就最后在把DongtaiProxy 和重写的main函数代码贴一下

      代码如下

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DongtaiProxy {

    //传入的是目标对象
    private Object object;

    public DongtaiProxy(Object object){
        this.object = object;
    }

    public Object getProxyInstance(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        return method.invoke(object,args);
                    }
                });
    }
}
import proxy.jingtaiProxy.GirlUser;
import proxy.jingtaiProxy.IUserDao;

public class Main {

    public static void main(String[] args){
        //代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
        IUserDao iUserDao = new GirlUser();
        IUserDao proxy    = (IUserDao) new DongtaiProxy(iUserDao).getProxyInstance();
        proxy.noLove();
    }
}

      运行结果如图:

    3.3 cglib动态代理

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>

      3.3.1 Girl、CglibProxy、main函数,重新贴一下这个cglib代理的代码    

public class Girl {
    public void love(){
        System.out.println("爱家人爱朋友爱和平!");
    }
}
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy {

    private Object target;

    public CglibProxy(Object target){
        this.target = target;
    }

    public Object getProxyInstance(){

        //org.springframework.cglib.proxy.Enhancer cglib中的一个工具类
        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(target.getClass());

        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

                Object result = method.invoke(target,objects);
                return result;
            }
        });

        //创建子类对象
        return enhancer.create();

    }
}
public class main {

    public static void main(String[]  args){

        Girl girl        = new Girl();

        Girl proxy = (Girl) new CglibProxy(girl).getProxyInstance();

        proxy.love();

    }
}

        运行结果

    
4、应用场景

      最典型的就是Spring AOP,它就是根据代理模式实现的,当然还有我上面讲的反射。

      4.1、先说反射,只是大概说下,反射在我们工作中应用的还是比较多的,比如我们的eclipse、idea,当我们输入一个对象的时候,只要一点就会出现它相应的方法和属性,还有它能够开发各种通用的框架,struts2举例

      我们前端请求的是ModifyLoginPasswordAction,那么我们就会解析这个struts.xml文件,然后找到方法是sms4LoginPwd的action,然后创建这个action的实例,去调用execute()执行后台代码,就讲到了这里,主要说设计模式。

      4.2 spring aop 用到的代理设计模式

      它主要用到jdk动态代理设计以及cglib动态代理设计,spring aop怎么用到的呢,它会判断你的目标对象类有木有实现接口,然后做一个判断,如图

    

      在说下aop应用在那些场景呢?事物管理,日志,缓存等等...

      说下事物配置?我们都是在xml文件配置相关属性,如图

    

      然后看到我红色标出来的那个类了吗,进去看一下!

      这个类里面封装了很多控制事物的方法,commit(),begin()...等等,因为文件太大我只截图一部分,所以我们在项目开发中就在事物方面一直用这些方法,但是绝对不会创建这个类的实例,因为这是spring核心内部的类,怎么可能是我们随随便便拿出来new的,所以我们只能通过代理模式用这个类的事物控制方法,同理好多类我们也如此!

      希望大家记住代理设计模式在我看来就是,框架里面的部分核心类,官方的部分类,咱就不直接new,用另外一种方式用他们的方法,就是代理!为什么不直接 new,看下面

      在实际的项目中,在你通往架构师的道路上,你要培养出一种感觉:要new一个实体对象是件很谨慎的事情(不是指值对象),不要随便new。最好不要自己new,让别人去new,传给你去调用。这样new错了也是别人的事,换而言之你的模块是好质量的,禁得起推敲的。那么都不愿意去new,谁去new?你可以通过代理模式获取该类实例,获取对应的方法,当然还有另外一种代替new的,那就是用抽象工厂模式,下一节讲解!

展开阅读全文
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部