代理模式

代理模式

静态代理

优点

业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合)

缺点

代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。

接口

public interface Rent {
    void rent();
}

目标类

public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房屋出租");
    }
}

代理类

public class HostProxy implements Rent{
    Host host;
    public HostProxy(Host host1){
        this.host=host1;
    }
    @Override
    public void rent() {
        System.out.println("事务开始");
        host.rent();
        System.out.println("提交");
    }
}

客户

public class Client {
    public static void main(String[] args) {
        //静态代理
        Host host = new Host();
        HostProxy hostProxy = new HostProxy(host);
        hostProxy.rent();
    }
}

动态代理

jdk实现

需要被代理类实现有接口,然后通过Proxy类的newProxyInstance(ClassLoader loader,Class<?> interface,InvocationHandler h)方法创建

接口

public interface UserDao {
    int add(int a,int b);
    String paste(String str);
}

被代理类:需要有实现接口

public class User implements UserDao{
    @Override
    public int add(int a, int b) {
        return a+b;
    }
    @Override
    public String paste(String str) {
        return str;
    }
}

代理类:需要传入被代理的对象

newProxyInstance方法参数解释ClassLoader loader,Class<?> interface,invocationHandler h

ClassLoader loader:获取类加载器

Class<?> interface:被代理类的接口类型,可以是一个数组

InvocationHandler h:具体执行代理的接口

public class UserProxy {
    private Object target;
    public UserProxy(Object obj){
        target = obj;
    }
    public Object getProxy(){
        return Proxy.newProxyInstance(UserDao.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke = null;
                System.out.println(method.getName());
                if (method.getName().equals("add")){
                    System.out.println("开始增强");
                    invoke = method.invoke(target, args);
                    System.out.println("方法执行完毕");
                }
                return invoke;
            }
        });
    }
}

客户端调用以及结果输出

cglib实现

此方式不要求被代理类为接口的实现类,cglib基于继承被代理类实现的

需要先引入相关依赖

<dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.1</version>
        </dependency>

被代理的类

public class HelloCglib {
        public void sayHello() {
            System.out.println("CGLIB动态代理模式!");
        }
}

cglib代理类

public class CglibProxy implements MethodInterceptor {
    /**
     * 指定cglib代理模式的代理类
     */
    private final Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        //设置超类方法
        enhancer.setSuperclass(this.target.getClass());
        //设置一个回调方法,用来设置哪个类为代理类,this表示当前类为代理类
        enhancer.setCallback(this);
        //创建代理对象
        return enhancer.create();
    }
    public Object intercept(Object obj,
                            Method method, Object[] args,
                            MethodProxy proxy) throws Throwable {
        System.out.println("CGLIB代理前");
        Object object = proxy.invokeSuper(obj, args);
        System.out.println("CGLIB代理后");
        return object;
    }
}

客户端演示

public class HelloClient {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy(new HelloCglib());
        HelloCglib proxy = (HelloCglib) cglibProxy.getProxy();
        proxy.sayHello();
    }
}

.

posted @ 2022-10-22 15:39  happy_in  阅读(21)  评论(0)    收藏  举报