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;
}
}