Java 代理模式

0.代理的概念:

代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。

1.静态代理:

优点:静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展。
不足:静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。

public interface UserDao {
	public int add(int a,int b);
	public String update(String name);
}
public class UserDaoImpl2 implements UserDao {

	@Override
	public int add(int a, int b) {
		System.out.println("UserDaoImpl 2--add执行了");
		return a+b;
	}

	@Override
	public String update(String name) {
		System.out.println("UserDaoImpl 2--update执行了");
		return name;
	}

}
public class UserDaoStaticProxy implements UserDao{
	
	public UserDao userdao;
	
	public UserDaoStaticProxy(UserDao userdao) {
		this.userdao = userdao;
	}
	
	public static void main(String[] args) {
		
		UserDaoImpl2 userDao2 = new UserDaoImpl2();
		UserDaoStaticProxy udsp = new UserDaoStaticProxy(userDao2);
		
		System.out.println("Static Proxy add result: "+udsp.add(1, 2));
		System.out.println("===================================");
		System.out.println("Static Proxy update result: "+udsp.update("hello shanghai"));
	}

	@Override
	public int add(int a, int b) {
 		//增强
		System.out.println("UserDaoStaticProxy--add执行了");
		userdao.add(a, b);
		return a+b;
	}

	@Override
	public String update(String name) {
 		//增强
		System.out.println("UserDaoStaticProxy--update执行了");
		userdao.update(name);
		return name;
	}

}

2.动态代理(JDK动态代理):

为解决静态代理对象必须实现接口的所有方法的问题,Java给出了动态代理,动态代理具有如下特点:
1.Proxy对象不需要implements接口;
2.Proxy对象的生成利用JDK的Api,在JVM内存中动态的构建Proxy对象。
* Proxy.newProxyInstance()
* 三个参数解析:
* 第一: 需要实现增强类的加载器,这里指的是UserDaoImpl
* 第二: 需要增强的类的接口数组,这里只有一个UserDao
* 第三: 实现了InvocationHandler接口的类,这里面进行增强操作,
* 多种方式: 1 匿名内部类
* 2 正常类实现InvocationHandler接口

public interface UserDao {
	public int add(int a,int b);
	public String update(String name);
}
public class UserDaoImpl implements UserDao {

	@Override
	public int add(int a, int b) {
		System.out.println("UserDaoImpl--add执行了");
		return a+b;
	}

	@Override
	public String update(String name) {
		System.out.println("UserDaoImpl--update执行了");
		return name;
	}

}
public class UserDaoProxy {

	public static void main(String[] args) {
		
		Class<?>[] interfaces = {UserDao.class};
		/*
		 * Proxy.newProxyInstance()
		 * 三个参数解析:
		 * 第一: 需要实现增强类的加载器,这里指的是UserDaoImpl
		 * 第二: 需要增强的类的接口数组,这里只有一个UserDao
		 * 第三: 实现了InvocationHandler接口的类,这里面进行增强操作,
		 * 				多种方式:	1 匿名内部类
		 * 					   	2 正常类实现InvocationHandler接口
		 * */
		//1 匿名内部类
//		UserDao newProxyInstance = (UserDao)Proxy.newProxyInstance(UserDaoImpl.class.getClassLoader(), interfaces , new InvocationHandler() {
//			
//			@Override
//			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//
//				//之前增强
//				System.out.println("增强方法之前执行了..."+method.getName()+" 执行参数为: "+Arrays.toString(args));
//				//增强方法执行
//				Object invoke = method.invoke(new UserDaoImpl(), args);
//				
//				//之后增强
//				System.out.println("增强方法之后执行了..."+" 返回为: "+invoke);
//				
//				return invoke;
//			}
//		});
		
		//2 正常类实现InvocationHandler接口
		ProxyHandler proxyHandler = new ProxyHandler(new UserDaoImpl());
		UserDao newProxyInstance = (UserDao)Proxy.newProxyInstance(UserDaoImpl.class.getClassLoader()
									, interfaces 
									, proxyHandler);					
		newProxyInstance.add(12, 1);
	}
}

class ProxyHandler implements InvocationHandler{
	public Object obj;
	
	public ProxyHandler(Object obj) {
		this.obj = obj;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//之前增强
		System.out.println("增强方法之前执行了..."+method.getName()+" 执行参数为: "+Arrays.toString(args));
		//增强方法执行
		Object invoke = method.invoke(obj, args);
		
		//之后增强
		System.out.println("增强方法之后执行了..."+" 返回为: "+invoke);
		
		return invoke;
	}
	
}

3.动态代理(CGLIB动态代理):

对于未实现接口的普通对象,需要代理就需要CGLIB(Code Generation Library)动态代理
原理:通过构建一个子类对象,实现对该对象的代理,需要目标对象不能是final类,且方法不能为finalh或static。
CGLIB需要依赖jar包:
maven依赖:

  <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.10</version>
  </dependency>
public class UserCGLIBService {
	
	public void execute() {
		System.out.println("修改管理系统数据。");
	} 
	
	public String getName(String name) {
		System.out.println("查看管理系统数据。");
		return name;
	}
}
public class UserCGLIBProxy implements MethodInterceptor{

//	public Object obj;
//	
//	public UserCGLIBProxy(Object obj) {
//		this.obj = obj;
//	}
//	
//	//给目标对象创建一个代理对象进行配置
//	public Object getConfig() {
//		//工具类
//		Enhancer en = new Enhancer();
//		//设置父类
//		en.setSuperclass(obj.getClass());
//		//设置回调函数
//		en.setCallback(this);
//		//创建子类代理对象
//		return en.create();
//	}
	/*
	 * intercept()的参数:
	 * obj 表示增强的对象,即实现这个接口类的一个对象
	 * method 表示要被拦截的方法
	 * args 表示要被拦截的参数
	 * proxy 表示要触发父类的方法对象
	 * */
	@Override
	public Object intercept(Object object, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
		//之前增强
		System.out.println("增强之前执行了操作.方法:"+method.getName()+" 参数: "+Arrays.toString(arg2));
		
		//增强方法执行
//		Object invoke = method.invoke(object,arg2);
		Object invoke = methodProxy.invokeSuper(object, arg2);
		
		//之后增强
		System.out.println("增强之后执行了操作.返回: "+invoke);
		
		return invoke;
	}

}
public class TestCGLIBProxy {

	public static void main(String[] args) {
//		UserCGLIBService userCGLIBService = new UserCGLIBService();
//		UserCGLIBProxy userCGLIBProxy = new UserCGLIBProxy(userCGLIBService);		
//		//代理
//		UserCGLIBService proxy = (UserCGLIBService)userCGLIBProxy.getConfig();
		
		
		Enhancer en = new Enhancer();
		//设置父类,指的是需要增强的类-->UserCGLIBService
		en.setSuperclass(UserCGLIBService.class);
		//设置回调函数,需要指定增强类-->UserCGLIBProxy
		en.setCallback(new UserCGLIBProxy());
		//创建子类代理对象,需要强转为 --> UserCGLIBService
		UserCGLIBService proxy = (UserCGLIBService)en.create();
		
		
		proxy.execute();
		proxy.getName("Shanghai");
	}

}
posted @ 2021-02-08 17:28  方罗良  阅读(85)  评论(0)    收藏  举报