(13)Spring学习记录---Spring_bean(AOP基础)

先来实现一个实例 

1.创建接口ArithmeticCalulator

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

2.实现ArithmeticCalulatorImpl,并加入日志信息

public class ArithmeticCalulatorImpl implements ArtithmeticCaclulator {

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

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

	}

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

	}

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

	}

}

3.Main

public class Main {
	public static void main(String[] args) {
		
		
		ArtithmeticCaclulator artithmeticCaclulator =new ArithmeticCalulatorImpl();
		
		int result=artithmeticCaclulator.add(1, 2);
		System.out.println("->>"+result);
		
		result=artithmeticCaclulator.sub(3, 2);
		System.out.println("->>"+result);
	}
}

4.结果

可以看到这些日记信息都十分相似,而且当我加入这些日志信息后,有时候会和业务代码混淆,难以区分。不利于我们的维护。

解决方法一:

1.动态代理

AritimeticCalulatorLoggingProxy.class

public class AritimeticCalulatorLoggingProxy {
	
	//要代理的对象
	private ArtithmeticCaclulator target;
	
	public AritimeticCalulatorLoggingProxy(ArtithmeticCaclulator target) {
		this.target = target;
	}

	public ArtithmeticCaclulator getLoggingProxy() {
		ArtithmeticCaclulator proxy=null;
		
		//代理对象由哪个类加载器加载
		ClassLoader loader=target.getClass().getClassLoader();	
		
		//代理对象的类型 包括其中的方法
		Class  [] interfaces =new Class[] {ArtithmeticCaclulator.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	+" begin with "+	Arrays.asList(args));
				//执行方法
				Object result  = method.invoke(target, args);
				//日志
				System.out.println("The method "+ methodname +	" end with " + result);
				return result;
			}
		};
		
		
		proxy=(ArtithmeticCaclulator)Proxy.newProxyInstance(loader, interfaces, h);
		
		return proxy;
	}
}

 我们把公共代码写在InvocationHandler里面。同时去除ArithmeticCalulatorImpl的日志信息。

修改Main方法 ,通过代理调用方法

public class Main {
	public static void main(String[] args) {
		
		ArtithmeticCaclulator target=new ArithmeticCalulatorImpl();
		ArtithmeticCaclulator proxy= new AritimeticCalulatorLoggingProxy(target).getLoggingProxy();
		
		
		int result=proxy.add(1, 2);
		System.out.println("->>"+result);
		
		result=proxy.sub(3, 2);
		System.out.println("->>"+result);
		
	}
}

结果:

 

我们可以引入这样一种思想,将业务代码和日志代码以某种形式分离开来,由于他们是同一层的(横向的),所有我们可以像上面的例子用Proxy分离。但是实际中肯定不能这么做,一是维护成本高,二是对程序员要求也高。

我们可以利用Aop编程的思想来解决代码分离的问题。

AOP简介

术语

1.切面:我们将日志抽取出来,作为一个切面,将验证抽取出来,作为一个切面,将业务逻辑抽取出来,作为一个切面。这些切面都叫做横切关注点。

2.通知:切面里的每一个方法都是一个通知。它是每个切面必须完成的工作。

3.目标:被通知的对象,这里是add(),mul(),div(),sub()。

4.代理:通知目标后,业务逻辑和日志必须有一个结合,这样的结果就是产生一个代理。

5.连接点:以方法执行为评判标准,执行前后中,异常抛出时等等。。相当于一个被查询的数据。是切点的定位目标

6.切点:aop通过切点定位到连接点,看不见摸不着。相当于查询条件。

猜你喜欢

转载自blog.csdn.net/ck784101777/article/details/83141931