java代理模式

Java代理模式

  代理(Proxy)是一种常用的设计模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。目的就是在不需要修改原有的代码情况下扩展原功能。

静态代理

1.创建服务类接口

package com.zhang.proxy.staticProxy;

public interface UserInterface {

    void save();
}

2.实现服务接口

package com.zhang.proxy.staticProxy;

public class UserImpl implements UserInterface{
    public void save() {
        System.out.println("执行User的save方法");
    }
}

3.创建代理类

package com.zhang.proxy.staticProxy;

public class UserProxy implements UserInterface {
    private UserImpl target;
    public UserProxy(UserImpl target) {
        this.target = target ;
    }
    public void save() {
        System.out.println("开始执行代理类");
        target.save();
        System.out.println("结束执行代理类");
    }
}

4.可以来测试啦

package com.zhang.proxy.staticProxy;

public class Test_20180319_01 {

    public static void main(String[] args){
        UserImpl user = new UserImpl();
        UserProxy userProxy = new UserProxy(user);
        userProxy.save();
    }
}

静态代理总结:
  可以做到不修改原服务代码的情况下对目标对象进行功能的扩展,但为们需要为每一个服务都创建一个代理类,工作量有些大,同时接口发生改变,代理类也需要改变。

jdk动态代理

  在动态代理中我们只需要写一个动态处理器。JDK运行时为我们动态创建代理对象。
1.创建目标对象接口

package com.zhang.proxy.jdkProxy;

public interface UserService {

    public void add();
}

2.创建目标对象实现类

package com.zhang.proxy.jdkProxy;

public class UserServiceImpl implements UserService {

    public void add() {
        System.out.println("执行UserServiceImpl的add方法");
    }
}

3.编写jdk动态处理器

package com.zhang.proxy.jdkProxy;

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

/**
 * @Description : jdk动态代理
 * @Author : zhangMing
 * @Date : Created in 下午4:13 2018/3/19
 */
public class MyInvocationHandler implements InvocationHandler {

    private Object target;

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

    /**
     * 执行目标对象方法
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行目标方法前");
        Object result = method.invoke(target,args);
        System.out.println("执行目标方法后");
        return result;
    }

    /**
     * 获取目标对象的代理对象
     * @return 代理对象
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                this.target.getClass().getInterfaces(),this);
    }
}

4.编写测试类

package com.zhang.proxy.jdkProxy;

public class Test_20180319_02 {

    public static void main(String[] args){
        //实例化目标对象
        UserService userService = new UserServiceImpl();
        //实例化Invocation
        MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
        //根据目标生成代理对象
        UserService proxy = (UserService) invocationHandler.getProxy();
        //调用代理对象方法
        proxy.add();
    }
}

Proxy.newProxyInstance()方法接受的三个参数:
  1.当前目标对象使用的类加载器
  2.制定目标对象实现的接口类型
  3.指定动态处理器,执行目标对象时触发处理器的方法
jdk动态代理总结:
  对比静态代理,动态代理减少了为们开发任务,同时降低了对接口的耦合度。遗憾的是只能对实现了接口的类进行代理。

cglib代理

  由于Jdk动态代理只能对实现了接口的类进行代理。那么对于没有接口的类,就需要cglib了。
1.引入jar包

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

2.创建目标对象

package com.zhang.proxy.cglibProxy;

public class User {

    public void add(){
        System.out.println("执行User的add方法");
    }

}

3.创建cglib代理类

package com.zhang.proxy.cglibProxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class UserCglib implements MethodInterceptor{

    private Object target;
    /**
     * 创建代理对象
     * @param target
     * @return
     */
    public Object getInstance(Object target){
        this.target = target;
        Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(this.target.getClass());
        //回调方法
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 回调方法
     * @param o
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行目标方法之前");
        methodProxy.invokeSuper(o,objects);
        System.out.println("执行目标方法之后");
        return null;
    }

}

4.创建测试类

package com.zhang.proxy.cglibProxy;

public class Test_20180319_03 {

    public static void main(String[] arg){
        UserCglib userCglib = new UserCglib();
        User user = (User)userCglib.getInstance(new User());
        user.add();
    }
}

cglib代理总结:
  cglib创建的动态代理对象比JDK创建的性能更高,代价是创建时花费的时间也多的多。所以对于单例对象,采用cglib更合适。cglib采用动态创建子类的方法,对于final修饰的方法无法进行代理。

拓展Spring aop

  Spring 默认采用JDK动态代理,如果要被代理的对象不是实现类,那么Spring会强制使用CGLib来实现动态代理。

<aop:config proxy-target-class="true">
    <!-- 切面详细配置 -->
</aop:config>

target=true为cglib代理。默认为false

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值