设计模式笔记-代理模式

Posted SingleOneMan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式笔记-代理模式相关的知识,希望对你有一定的参考价值。

设计模式笔记-代理模式

文章目录

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中的代理模式

以上是关于设计模式笔记-代理模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习笔记之代理模式

大话设计模式读书笔记——代理模式

代理模式——HeadFirst设计模式学习笔记

设计模式学习笔记--代理模式

设计模式之代理模式笔记

设计模式 - 学习笔记 - 代理模式ProxyPattern