java代理模式

最近学习了代理模式,在此做一个记录

一、概念

1、代理模式解决的问题:将主要业务、次要业务解耦

2、代理模式的本质:监听某一种行为,当改行为发生的时候对行为进行修饰,此处行为可以看做主要业务,修饰可以看成次要业务

3、代理模式的组成:

      a、业务接口:申明需要被监听的行为

      b、代理实现类(InvocationHandler):次要业务,次要业务和主要业务绑定执行

  c、代理对象(监听对象)

 

二、静态代理和动态代理

1、静态代理

a、接口

/**
 * @program: demo
 * @description: 接口
 * @author: bang.chen
 * @create: 2018-06-25 22:21
 **/
public interface IUserDao {
     void save();
}

 

b、接口实现类、目标对象

/**
 * @program: demo
 * @description: 接口实现、目标对象
 * @author: bang.chen
 * @create: 2018-06-25 22:22
 **/
public class UserDao implements IUserDao{
    @Override
    public void save() {
        System.out.println("数据已经保存");
    }
}

  

c、代理类

/**
 * @program: demo
 * @description:代理类
 * @author: bang.chen
 * @create: 2018-06-25 22:24
 **/
public class UserProxy implements IUserDao{
    private IUserDao target;

    public UserProxy(IUserDao target){
         this.target = target;
    }

    @Override
    public void save() {
        System.out.println("before do something.....");
        target.save();
        System.out.println("after do something......");
    }
}

  

d、客户端测试

/**
 * @program: demo
 * @description: 客户端
 * @author: bang.chen
 * @create: 2018-06-25 22:27
 **/
public class App {
    public static void main(String[] args) {
        UserDao userDao = new UserDao();
        UserProxy userProxy = new UserProxy(userDao);

        userProxy.save();
    }
}

 

输出结果

before do something.....
数据已经保存
after do something......

 通过静态代理,已经对目标对象的行为进行了修饰

 

在实际开发中,一般不涉及静态代理,一般用到的都是动态代理,下面对动态代理进行介绍

 

2、动态代理

业务场景如下:

主要业务:吃法,便便;次要业务:洗手

a、业务接口

/**
 * Created by chenbang on 2019/12/9.
 * 业务接口
 */
public interface BaseService {
     void eatFood(String food);

     void wcing(String str);

}

 

b、代理对象实现类

/**
 * Created by chenbang on 2019/12/9.
 * 代理对象
 */
public class Agent implements InvocationHandler {

    private BaseService baseService;


    public Agent(BaseService baseService) {
        this.baseService = baseService;
    }

    /**
     *
     * @param proxy 监听对象
     * @param method 监听方法
     * @param args 监听方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        if (methodName.equals("eatFood")){
            wash();
            method.invoke(baseService, args);
        }else if(methodName.equals("wcing")){
            method.invoke(baseService, args);
            wash();
        }
        return null;
    }


    private void wash(){
        System.out.println("洗手");
    }
}

 

c、代理工厂(用于创建代理类、监听对象)

/**
 * Created by chenbang on 2019/12/9.
 * 代理工厂
 */
public class ProxyFactory {
    public static BaseService newInstance(Class classFile) throws IllegalAccessException, InstantiationException {


        BaseService baseService = (BaseService) classFile.newInstance();
        //获取一个代理对象
        InvocationHandler agent = new Agent(baseService);

        //注册一个对特定行为监控的对象


        Class classArray[] = {BaseService.class};
        /**
         * classLoader:指向别监控的类文件在内存中的地址
         * classArray:被监听的类中接口
         */
        return (BaseService) Proxy.newProxyInstance(BaseService.class.getClassLoader(), classArray, agent);
    }

}

 

 

d、业务实现类

/**
 * Created by chenbang on 2019/12/9.
 */
public class Person  implements BaseService{

    @Override
    public void eatFood(String food) {
        System.out.println("狼吞虎咽吃"+food);
    }

    @Override
    public void wcing(String str) {
        System.out.println("舒爽的"+str);
    }
}





/**
 * Created by chenbang on 2019/12/9.
 */
public class Dog implements BaseService{

    @Override
    public void eatFood(String food) {
        System.out.println("吭"+food);
    }

    @Override
    public void wcing(String str) {
        System.out.println("三腿立"+str);
    }
}

 

e、测试类

/**
 * Created by chenbang on 2019/12/9.
 */
public class TestMain {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
//        BaseService service = ProxyFactory.newInstance();
//        service.eatFood("");
        BaseService xiaoming = ProxyFactory.newInstance(Person.class);
        xiaoming.eatFood("鸡");

        BaseService dog = ProxyFactory.newInstance(Dog.class);
        dog.eatFood("骨头");

    }
}

  

输出结果

洗手
狼吞虎咽吃鸡
Disconnected from the target VM, address: '127.0.0.1:52347', transport: 'socket'
洗手
吭骨头

  

总结

代理模式在开发中的使用简化了开发内容的复杂对,开发人员只需要关注主要业务,次要业务可以通过代理模式解决;实际使用的案例有,mybatis的面向接口编程,springAop......

 

posted @ 2019-12-10 23:18  happyfresher  阅读(209)  评论(0编辑  收藏  举报