设计模式笔记-代理模式

设计模式笔记-代理模式

文章目录

  • 设计模式笔记-代理模式
    • **1.代理模式**
    • 2.常见写法
    • 3.常见框架中的代理模式

1.代理模式

静态代理:静态代理提前编译,代码运行前,直接调用代理类的方法。动态代理是在程序运行时通过反射机制动态创建的。

jdk动态代理:运行期通过反射,调用代理类的方法

cglib代理:CGLib采用了字节码技术,其原理是通过字节码技术为一个代理类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑

2.常见写法

静态代理:

public interface IUserDao {
    void save();
}
/**
 * 接口实现
 * 目标对象
 */
public class UserDao implements IUserDao {
    public void save() {
        System.out.println("----已经保存数据!----");
    }
}

/**
 * 代理对象,静态代理
 */
public class UserDaoProxy implements IUserDao{
    //接收保存目标对象
    private IUserDao target;
    public UserDaoProxy(IUserDao target){
        this.target=target;
    }

    public void save() {
        System.out.println("开始...");
        target.save();//执行目标对象的方法
        System.out.println("结束...");
    }
}

public class TestMain {

	 public static void main(String[] args) {
	        //目标对象
	        UserDao target = new UserDao();
	        //代理对象,把目标对象传给代理对象,建立代理关系
	        UserDaoProxy proxy = new UserDaoProxy(target);
			//执行的是代理的方法
	        proxy.save();
	    }
}

jdk动态代理:

public interface IUserDao {
    void save();
}
/**
 * 接口实现
 * 目标对象
 */
public class UserDao implements IUserDao {
    public void save() {
        System.out.println("----已经保存数据!----");
    }
}
public class ProxyFactory{

    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

    /**
     * Proxy.newProxyInstance()方法接受三个参数:
     *
     * ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的
     * Class[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
     * InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法
     * @return
     */
   //给目标对象生成代理对象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //这里就可以进行所谓的AOP编程了
                        //在调用具体函数方法前,执行功能处理
                        System.out.println("开始...");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        //在调用具体函数方法后,执行功能处理
                        System.out.println("结束...");
                        return returnValue;
                    }
                }
        );
    }

}

/**
 * jdk动态代理运行期通过反射,调用代理类的方法
 */
public class TestMain {
	public static void main(String[] args) {
        // 目标对象
        IUserDao target = new UserDao();
        // 【原始的类型 】
        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法   【代理对象】
        proxy.save();
    }
}

cglib代理:

/**
 * 目标对象,没有实现任何接口
 */
public class UserDao {

    public void save() {
        System.out.println("----已经保存数据!----");
    }
}
/**
 * Cglib子类代理工厂
 * 对UserDao在内存中动态构建一个子类对象
 * 2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
 */
public class ProxyFactory implements MethodInterceptor {
    //维护目标对象
    private Object target;

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

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();

    }

    /**
     * //obj是代理后的子类  ,method是调用方法 ,args是方法入参 , proxy是MethodProxy代理对象
     * @param obj
     * @param method
     * @param args
     * @param proxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始...");
        //执行目标对象的方法,invoke方法调用的对象没有增强过,invokeSuper方法调用的对象已经是增强了的
        Object returnValue = proxy.invokeSuper(target, args);
        System.out.println("结束...");

        return returnValue;
    }

/**
 * CGLib采用了字节码技术,其原理是通过字节码技术为一个代理类创建子类,
 * 并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑
 */
public class TestMain {
	public static void main(String[] args) {
		//目标对象
        UserDao target = new UserDao();

        //代理对象// 生成 Cglib 代理类
        UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();

        //执行代理对象的方法
        proxy.save();
    }
}

3.常见框架中的代理模式

1.AOP用代理模式实现的,有JDK动态代理(需要实现接口)和CGLib代理

2.dubbo中的代理模式

你可能感兴趣的:(设计模式)