spring aop角度讲解静态代理,动态代理过程

一般代码

接口,实现

package priv.dengjl.proxy.bean;

public interface IPersonService {

	void sayHello();

	void printName();

	void test();

}

package priv.dengjl.proxy.bean;

/**
 * 业务代码,普通业务开发员工编写
 * 
 * @author it
 */
public class PersonService implements IPersonService {
	
	@Override
	public void sayHello() {
		System.out.println("sayHello");
	}
	
	@Override
	public void printName() {
		System.out.println("printName");
	}
	
	@Override
	public void test() {
		System.out.println("test");
		throw new RuntimeException("抛出测试异常!!!");
	}
}

测试类

package priv.dengjl.proxy.test;

import priv.dengjl.proxy.bean.IPersonService;
import priv.dengjl.proxy.bean.PersonService;

public class App {
	public static void main(String[] args) {
		
		IPersonService service = new PersonService();
		System.out.println("====================");
		service.sayHello();
		System.out.println("====================");
		service.printName();
		System.out.println("====================");
		service.test();
		System.out.println("====================");
	}
}

测试结果

====================
sayHello
====================
printName
====================
test
Exception in thread "main" java.lang.RuntimeException: 抛出测试异常!!!
	at priv.dengjl.proxy.bean.PersonService.test(PersonService.java:23)
	at priv.dengjl.proxy.test.App.main(App.java:15)

引入静态代理

对原业务类具备了控制作用

package priv.dengjl.proxy.highproxy;

import priv.dengjl.proxy.bean.IPersonService;
import priv.dengjl.proxy.bean.PersonService;

/**
 * 系统控制,由高级业务人员编写
 * 
 * 这里简单处理,直接继承PersonService,
 * 使StaticPersonServiceProxy与PersonService保持类型一致,也可以不继承
 * 
 * 这里是为了简化代码,未用接口
 * 
 * @author it
 */
public class StaticPersonServiceProxy extends PersonService {
	
	private IPersonService service;

	public StaticPersonServiceProxy(IPersonService service) {
		this.service = service;
	}

	@Override
	public void sayHello() {
		System.out.println("dobefore");
		service.sayHello();
		System.out.println("doafter");
	}

	@Override
	public void printName() {
		System.out.println("dobefore");
		service.printName();
		System.out.println("doafter");
	}

	@Override
	public void test() {
		System.out.println("dobefore");
		try {
			service.test();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("doException");
		}
		System.out.println("doafter");
	}
	
	
	
}

测试类

package priv.dengjl.proxy.test;

import priv.dengjl.proxy.bean.IPersonService;
import priv.dengjl.proxy.bean.PersonService;
import priv.dengjl.proxy.highproxy.StaticPersonServiceProxy;

public class AppStaticProxy {
	public static void main(String[] args) {
		
		IPersonService service = new PersonService();
		//静态代理类
		IPersonService serviceProxy = new StaticPersonServiceProxy(service); 
		System.out.println("====================");
		serviceProxy.sayHello();
		System.out.println("====================");
		serviceProxy.printName();
		System.out.println("====================");
		serviceProxy.test();
		System.out.println("====================");
	}
}

测试结果

====================
dobefore
sayHello
doafter
====================
dobefore
printName
doafter
====================
dobefore
test
java.lang.RuntimeException: 抛出测试异常!!!
doException
doafter
====================
	at priv.dengjl.proxy.bean.PersonService.test(PersonService.java:23)
	at priv.dengjl.proxy.highproxy.StaticPersonServiceProxy.test(StaticPersonServiceProxy.java:42)
	at priv.dengjl.proxy.test.AppStaticProxy.main(AppStaticProxy.java:18)

引入动态代理

动态代理采用反射简化静态代理实现

package priv.dengjl.proxy.highproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import priv.dengjl.proxy.bean.IPersonService;

/**
 * 系统控制,由高级业务人员编写
 * 
 * 动态代理处理类
 * 
 * @author it
 */
public class DynamicPersonServiceProxy implements InvocationHandler {
	
	private IPersonService service;

	public DynamicPersonServiceProxy(IPersonService service) {
		this.service = service;
	}
	
	/**
	 * 代理了PersonService类所有方法,简化静态代理类
	 * 
	 * @Override
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("dobefore");
		try {
			return method.invoke(service, args);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("doException");
		}
		System.out.println("doafter");
		
		return null;
	}
	
	
	
}

测试

package priv.dengjl.proxy.test;

import java.lang.reflect.Proxy;

import priv.dengjl.proxy.bean.IPersonService;
import priv.dengjl.proxy.bean.PersonService;
import priv.dengjl.proxy.highproxy.DynamicPersonServiceProxy;

public class AppDynamicProxy {
	public static void main(String[] args) {

		IPersonService service = new PersonService();
		// 动态代理处理器
		DynamicPersonServiceProxy serviceProxyHandler = new DynamicPersonServiceProxy(service);
		IPersonService serviceProxy =  (IPersonService) Proxy.newProxyInstance(serviceProxyHandler.getClass().getClassLoader(), service.getClass().getInterfaces(), serviceProxyHandler);
		
		System.out.println("====================");
		serviceProxy.sayHello();
		System.out.println("====================");
		serviceProxy.printName();
		System.out.println("====================");
		serviceProxy.test();
		System.out.println("====================");
	}
}

测试结果,与静态代理一模一样

====================
dobefore
sayHello
====================
dobefore
printName
====================
dobefore
test
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at priv.dengjl.proxy.highproxy.DynamicPersonServiceProxy.invoke(DynamicPersonServiceProxy.java:31)
	at com.sun.proxy.$Proxy0.test(Unknown Source)
	at priv.dengjl.proxy.test.AppDynamicProxy.main(AppDynamicProxy.java:22)
Caused by: java.lang.RuntimeException: 抛出测试异常!!!
	at priv.dengjl.proxy.bean.PersonService.test(PersonService.java:23)
	... 7 more
doException
doafter
====================

动态代理切入点,颗粒度控制代理

只代理一部分方法,不代理所有

package priv.dengjl.proxy.highproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import priv.dengjl.proxy.bean.IPersonService;

/**
 * 系统控制,由高级业务人员编写
 * 
 * 动态代理处理类
 * 
 * @author it
 */
public class DynamicPersonServiceProxyPointcut implements InvocationHandler {
	
	private IPersonService service;

	public DynamicPersonServiceProxyPointcut(IPersonService service) {
		this.service = service;
	}
	
	/**
	 * 代理了PersonService类中的printName方法
	 * 
	 * @Override
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		String name = method.getName();
		
		// 只代理printName方法
		if ("printName".equals(name)) {
			Object object = null;
			System.out.println("dobefore");
			try {
				object = method.invoke(service, args);
			} catch (Exception e) {
				e.printStackTrace();
				System.out.println("doException");
			}
			System.out.println("doafter");
			return object;
		} else {
			return method.invoke(service, args);
		}
		
	}
	
	
	
}

测试

package priv.dengjl.proxy.test;

import java.lang.reflect.Proxy;

import priv.dengjl.proxy.bean.IPersonService;
import priv.dengjl.proxy.bean.PersonService;
import priv.dengjl.proxy.highproxy.DynamicPersonServiceProxyPointcut;

public class AppDynamicProxyPointCut {
	public static void main(String[] args) {

		IPersonService service = new PersonService();
		// 动态代理处理器,带有切面点的
		DynamicPersonServiceProxyPointcut serviceProxyHandler = new DynamicPersonServiceProxyPointcut(service);
		IPersonService serviceProxy =  (IPersonService) Proxy.newProxyInstance(serviceProxyHandler.getClass().getClassLoader(), service.getClass().getInterfaces(), serviceProxyHandler);
		
		System.out.println("====================");
		serviceProxy.sayHello();
		System.out.println("====================");
		serviceProxy.printName();
		System.out.println("====================");
		serviceProxy.test();
		System.out.println("====================");
	}
}

测试结果

====================
sayHello
====================
dobefore
printName
doafter
====================
test
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
	at com.sun.proxy.$Proxy0.test(Unknown Source)
	at priv.dengjl.proxy.test.AppDynamicProxyPointCut.main(AppDynamicProxyPointCut.java:22)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at priv.dengjl.proxy.highproxy.DynamicPersonServiceProxyPointcut.invoke(DynamicPersonServiceProxyPointcut.java:45)
	... 2 more
Caused by: java.lang.RuntimeException: 抛出测试异常!!!
	at priv.dengjl.proxy.bean.PersonService.test(PersonService.java:23)
	... 7 more

相关代码

https://github.com/dengjili/springaop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值