Spring框架学习笔记-AOP实现原理

JDK动态代理实现

JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy以及InvocationHandler。
JDK的动态代理实现AOP的步骤为:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
4.通过代理调用方法

首先我们需要创建一个UserService接口:

public interface UserService {
	public void addUser();
	public void updateUser();
	public void deleteUser();
}

然后还有实现类UserServiceImpl

public class UserServiceImpl implements UserService {
	public void addUser(){
		System.out.println("addUser()");
	}
	public void updateUser(){
		System.out.println("updateUser()");
	}
	public void deleteUser(){
		System.out.println("deleteUser()");
	}
}

然后我们需要切面类:用于存Advice通知 的MyAspect类,也就是存放我们的增强方法

public class MyAspect {
	public void before(){
		System.out.println("---before()---");
	}
	public void after(){
		System.out.println("---after()---");
	}
}

然后我们还需要工厂类MyBeanFactory ,这个类的主要的工作就是将我们的Advice通知(增强的代码)跟我们的target目标类结合起来生成proxy代理对象。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
public class MyBeanFactory{
	public static UserService createService(){
		//目标类
		final UserService userService=new UserServiceImpl();//当final修饰一个类时,表示这个类不能被继承。
		//切面类
		final MyAspect myAspect=new MyAspect();
		//代理类:将目标类和切面类进行结合
		UserService proxService=(UserService)Proxy.newProxyInstance(MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(),new InvocationHandler()/*每一个代理类的实例都对应一个相关联的动态代理类调用程序*/
				{public Object invoke(Object proxy,Method method,Object[] args)throws Throwable
					{myAspect.before();Object obj=method.invoke(userService,args);myAspect.after();return obj;}});
		return proxService;
	}
}

需要注意的是:InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法。
每一个动态代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用。

CGLib字节码加强实现

JDK自从1.3版本开始,就引入了动态代理,JDK的动态代理用起来非常简单,但是它有一个限制,就是使用动态代理的对象必须实现一个或多个接口 。如果想代理没有实现接口的类可以使用CGLib包。采用字节码增强框架CGLib,在运行时创建目标类的子类,从而对目标类进行增强。
首先和上面一样,我们需要目标类(注意!不需要接口!)

public class UserServiceImpl{
	public void addUser(){
		System.out.println("addUser()");
	}
	public void updateUser(){
		System.out.println("updateUser()");
	}
	public void deleteUser(){
		System.out.println("deleteUser()");
	}
}

然后我们需要切面类:用于存Advice通知 的MyAspect类,也就是存放我们的增强方法

public class MyAspect {
	public void before(){
		System.out.println("---before()---");
	}
	public void after(){
		System.out.println("---after()---");
	}
}

然后我们需要一个工厂类,采用cglib,底层创建目标类的子类。

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyBeanFactory{
	public static UserServiceImpl createService(){
		//目标类
		final UserServiceImpl userService=new UserServiceImpl();//当final修饰一个类时,表示这个类不能被继承。
		//切面类
		final MyAspect myAspect=new MyAspect();
		//代理类:采用cglib,底层创建目标类的子类
		//3.1核心类
		Enhancer enhancer=new Enhancer();
		//3.2确定父类
		enhancer.setSuperclass(userService.getClass());
		//3.3设置回调函数
		enhancer.setCallback(new MethodInterceptor(){
			public Object intercept(Object proxy,Method method,Object[] args,MethodProxy methodProxy)throws Throwable{
				myAspect.before();
				//执行目标类的方法
				Object obj=method.invoke(userService,args);
				//执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
				methodProxy.invokeSuper(proxy, args);
				myAspect.after();
				return obj;
			}	
		});
		//3.4创建代理
		UserServiceImpl proxService=(UserServiceImpl)enhancer.create();
		return proxService;
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值