代理模式

一:静态代理

1.概念

需要我们手写代理类,在程序运行前代理类已经存在。

注意:目标类和被代理类必须实现同一接口

2.实例

package com.zjt.test;
 
interface Duck {
    void swim();
}
 
class DuckImpl implements Duck{
    @Override
    public void swim() {
        System.out.println("小鸭子会游泳");
    }
}
 
class ProxyDuck implements Duck{
    Duck duck;   //一个空的构造函数,且代理类中明确声明需要代理的目标对象
    public ProxyDuck(){
        this.duck=new DuckImpl();
    }
 
    @Override
    public void swim() {
        System.out.println("噶嘎嘎。。。");
        duck.swim();
    }
}
 
class Test{
    public static void main(String[] args) {
        Duck duck = new ProxyDuck();
        duck.swim();
    }
}

二:动态代理

1.概念

在运行时运用反射动态生成代理类。

注意:目标类必须实现接口

2.实例

目标类接口

public interface TargetInterface {
	public void method1();
	public String method2();
	public int method3(int x);
}

目标类

public class Target implements TargetInterface{

	@Override
	public void method1() {
		System.out.println("method1 running...");
	}

	@Override
	public String method2() {
		System.out.println("method2 running...");
		return "method2";
	}

	@Override
	public int method3(int x) {
		return x;
	}
	
}

动态代理测试类

public class ProxyTest3 {
	@Test
	public void test1() throws IllegalArgumentException, ClassNotFoundException{
		//获得动态的代理对象---在运行时 在内存中动态的为Target创建一个虚拟的代理对象
		
		//objProxy是代理对象 根据参数确定到底是谁的代理对象
		TargetInterface objProxy=(TargetInterface)Proxy.newProxyInstance(
				Class.forName("eProxy.Target").getClassLoader(),	//与目标对象相同的类加载器 
				new Class[]{TargetInterface.class}, 
				new InvocationHandler() {
					@Override
					//invoke 代表的是执行代理对象的方法
					//method 代表目标对象的方法的字节码对象
					//args 代表目标对象的相应方法的参数
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("目标方法前的逻辑");
						//执行目标对象方法
						Object invoke = method.invoke(Class.forName("eProxy.Target").newInstance(), args);
						System.out.println("目标方法后的逻辑");
						return invoke;
					}
				}
		);
		objProxy.method1();
		String method2 = objProxy.method2();
		System.out.println(method2);
	} 

测试结果

3.应用场景

spring中的拦截器就是基于动态代理实现的。

三:CGLib代理

1.概念

①.第三方代理技术,cglib代理,可以对任何类生成代理。

②.代理的原理是对目标对象进行继承代理。

③.如果目标对象被final修饰,那么该类无法被cglib代理。

2.实例

目标类接口

public interface UserService {
	void save();
	void delete();
	void update();
	void find();
}

目标类

public class UserServiceImpl implements UserService{

	@Override
	public void save() {
		System.out.println("保存用户");
		//int i=1/0;
	}

	@Override
	public void delete() {
		System.out.println("删除用户");
		
	}

	@Override
	public void update() {
		System.out.println("更新用户");
		
	}

	@Override
	public void find() {
		System.out.println("寻找用户");
		
	}

}

CGLib代理类

public class UserServiceProxyFactory2 implements MethodInterceptor{

	public UserService getUserServiceProxy(){
		Enhancer en= new Enhancer();	//帮我们生成代理对象
		en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理
		en.setCallback(this);	//代理要做什么
		UserService us = (UserService) en.create();//创建代理对象
		return us;
	}
	
	@Override
	public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		//打开事务
		System.out.println("打开事务");
		//调用原有方法
		Object returnValue = methodProxy.invokeSuper(proxyObj, args);
		//提交事务
		System.out.println("提交事务");
		
		return returnValue;
	}
	
}

CGLibc测试类

public class Demo {
	//测试cglib代理
	@Test
	public void func2(){
		UserServiceProxyFactory2 factory2=new UserServiceProxyFactory2();
		UserService usProxy = factory2.getUserServiceProxy();
		usProxy.save();
		//代理对象继承了被代理对象==》true
		System.out.println(usProxy instanceof UserServiceImpl);//true
	}
}

测试结果

3.应用场景

springaop会使用CGLib代理当然被代理类有接口的情况下会优先使用动态代理。

四:参考

https://www.cnblogs.com/zjting/p/12547092.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值