Java笔记之动态代理

为什么要用动态代理?

•代码混乱:越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀.  每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.

•代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码. 如果日志需求发生变化, 必须修改所有模块.

问题:

普通代码:

 ArithmeticCalculator接口

package com.yorkmass.spring.aop.helloworld;

public interface ArithmeticCalculator {
	int add(int i,int j);
	int sub(int i,int j);
	int mul(int i,int j);
	int div(int i,int j);
	
}

 ArithmeticCalculatorLoggingImpl类

package com.yorkmass.spring.aop.helloworld;

public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {

	@Override
	public int add(int i, int j) {
		System.out.println("The method add begins with["+i+","+j+"]");
		int result=i+j;
		System.out.println("The method add ends with"+result);
		return result;
	}

	@Override
	public int sub(int i, int j) {
		System.out.println("The method sub begins with["+i+","+j+"]");
		int result=i-j;
		System.out.println("The method sub ends with"+result);
		return result;
	}

	@Override
	public int mul(int i, int j) {
		System.out.println("The method mul begins with["+i+","+j+"]");
		int result=i*j;
		System.out.println("The method mul ends with"+result);
		return result;
	}

	@Override
	public int div(int i, int j) {
		System.out.println("The method div begins with["+i+","+j+"]");
		int result=i/j;
		System.out.println("The method div ends with"+result);
		return result;
	}

}

然后自己写测试类运行即可

但是上面如果后期有需求需要对代码进行修改,则需要对每一行的日志文件进行修改,特别不方便修改。

我们能不能去掉每个方法的输入语句,只写一个,来实现对所有方法的日志管理,这样修改起来也比较方便,

动态代理便可以很好的解决这个问题。

 

使用动态代理解决问题

•代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.

动态代理解决办法:

我们把 ArithmeticCalculatorImpl类写的尽可能简单

 ArithmeticCalculatorImpl类

package com.yorkmass.spring.aop.helloworld;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

	@Override
	public int add(int i, int j) {
		int result=i+j;
		return result;
	}

	@Override
	public int sub(int i, int j) {
		int result=i-j;
		return result;
	}

	@Override
	public int mul(int i, int j) {
		int result=i*j;
		return result;
	}

	@Override
	public int div(int i, int j) {
		int result=i/j;
		return result;
	}

}

我们开始配置动态代理

ArithmeticCalculatorLoggingProxy类

package com.yorkmass.spring.aop.helloworld;

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

import javax.naming.spi.DirStateFactory.Result;

import org.omg.CORBA.PUBLIC_MEMBER;

public class ArithmeticCalculatorLoggingProxy {

	//要代理的对象
	private ArithmeticCalculator targer;
	public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
		// TODO Auto-generated constructor stub
		this.targer=target;
	}
	public ArithmeticCalculator getLoggingProxy(){
		ArithmeticCalculator proxy=null;
		//代理对象由哪一个类加载器负责加载
		ClassLoader loader=targer.getClass().getClassLoader();
		//代理对象的类型,即其中有哪些方法
		Class[] interfaces=new Class[]{ArithmeticCalculator.class};
		//当调用代理对象其中的方法时,该执行的代码
		InvocationHandler h=new InvocationHandler() {
			/**
			 * proxy:正在返回的那个代理对象,一般情况下,在invoke方法中都不适用该对象。
			 * method:正在调用的方法
			 * args:调用方法时,传入的参数
			 */
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				String methodName=method.getName();
				//日志
				System.out.println("The method..."+methodName+"begins with"+Arrays.asList(args));
				//执行方法
				Object result=method.invoke(targer, args);
				//日志
				System.out.println("The method"+methodName+"ends with "+result);
				return result;
			}
		};

		proxy=(ArithmeticCalculator)Proxy.newProxyInstance(loader, interfaces, h);
		return proxy;
	}
}

测试主类Main:

package com.yorkmass.spring.aop.helloworld;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		ArithmeticCalculator arithmeticCalculator=null;
//		arithmeticCalculator=new ArithmeticCalculatorLoggingImpl();
		ArithmeticCalculator target=new ArithmeticCalculatorImpl();
		ArithmeticCalculator proxy=new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
		int result=proxy.add(1, 2);
		System.out.println("-->"+result);
		result=proxy.div(4, 2);
		System.out.println("-->"+result);
		
	}

}

运行结果:

The method...addbegins with[1, 2]
The methodaddends with 3
-->3
The method...divbegins with[4, 2]
The methoddivends with 2
-->2

动态代理可以实现模块化编程 !

Spring AOP可以更好的解决这个问题,有兴趣请看博主spring AOP文章:https://blog.csdn.net/qq_36949176/article/details/86537951

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值