Java AOP动态代理

AOP 中的代理就是由 AOP 框架动态生成的一个对象,该对象可以作为目标对象使用。Spring 中的 AOP 代理,可以是 JDK 动态代理,也可以是 CGLIB代理。

jdk代理
JDK 动态代理是通过 java.lang.reflect.Proxy 类来实现的,我们可以调用 Proxy 类的 newProxylnstance()方法来创建代理对象。 对于使用业务接口的类, Spring默认会使用 JDK 动态代理来实现 AOP。
实现jdk动态代理,准备工作是要导入Spring相关的包,不会的话可以参考:Spring包的下载配置环境
随后创建一个接口,给接口定义俩个方法。

package jdk动态代理;

public interface UserDao {
	public void addUser();
	public void deleteUser();
}

再创建UserDao接口的实现类UserDaolmpl分别实现接口中的方法,并在每个方法中添加一条输出语句,

package jdk动态代理;

public class UserDaolmpl implements UserDao {
	public void addUser() {
		System.out.println("添加");
	}
	public void deleteUser() {
		System.out.println("删除");
	}
}

创建切面类MyAspect,在该类中定义一个模拟权限检查的方法和一个模拟记录日志的方法,这两个方法就表示切面中的通知

package jdk动态代理;

public class MyAspect {
	public void check_Permissions() {
		System.out.println("模拟检查权限. . . ");
	}
	public void log() {
		System.out.println("模拟记录日志. . . ");
	}
}

创建代理类 JdkProxy,该类需要实现InvocationHandler 接口,并编写代理方法。 在代理方法中,需要通过Proxy类实现动态代理,
JdkProxy 类实现了InvocationHandler接口,并实现了接口中的 invoke() 方法,所有动态代理类所调用的方法都会交由该方法处理。 在创建的代理方法createProxy()中, 使用了 Proxy 类的newProxylnstance()方法来创建代理对象。newProxylnstance()方法中包含3个参数,其中第 1 个参数是当前类的类加载器,第2个参数表示的是被代理对象实现的所有接口, 第3个参数this代表的就是代理类JdkProxy本身。在 invoke()方法中,目标类方法执行的前后,会分别执行切面类中的 check_Permissions()方法和 log()方法。

package jdk动态代理;

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

public class JdkProxy implements InvocationHandler {
	// 声明目标类接口
	private UserDao userDao;
	// 创建代理方法
	public Object createProxy(UserDao userDao) {
		this.userDao = userDao;
		// 1.类加载器
		ClassLoader classLoader = JdkProxy.class.getClassLoader();
		// 2.被代理对象实现的所有接口
		Class[] clazz = userDao.getClass().getInterfaces();
		// 3.使用代理类,进行增强j 返回的是代理后的对象
		return Proxy.newProxyInstance(classLoader, clazz, this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//声明切面
		MyAspect myAspect = new MyAspect(); 
		//前增强
		myAspect.check_Permissions(); 
		//在目标类上调用方法,并传入参数 
		Object obj = method.invoke(userDao, args); 
		//后增强
		myAspect.log(); 
		return obj;
	}
}

最后定义一个测试类,在该类中的 mainO方法中创建代理对象和目标对象,然后从代理对象中获得对目标对象userDao增强后的对象,最后调用该对象中的添加和删除方法

package jdk动态代理;

public class JdkTest {
	public static void main(String[] args) {
		JdkProxy jdkproxy = new JdkProxy();
		// 创建目标对象
		UserDao userDao = new UserDaolmpl();
		// 从代理对象中获取增强后的日标对象
		UserDao userDao1 = (UserDao) jdkproxy.createProxy(userDao);
		userDao1.addUser();
		userDao1.deleteUser();
	}
}

CGLIB代理
JDK 动态代理的使用非常简单,但它还有一定的局限性一一使用动态代理的对象必须实现一 个或多个接口 。 如果要对没有实现接口的类进行代理,那么可以使用 CGL旧代理。
CGL旧( Code Generation Library )是一个高性能开源的代码生成包,它采用非常底层的字 节码技术,对指定的目标类生成一个子类,并对子类进行增强。在Spring的核心包中已经集成 了 CGL旧所需要的包,所以开发中不需要另外导入 JAR 包。
首先创建一个目标类 UserDaoUserDao不需要实现任何接口,只需定义一个添加用户的方法和一个删除用户的方法,

package Cglib代理;

public class UserDao {
	public void addUser() {
		System.out.println("添加");
	}
	public void deleteUser() {
		System.out.println("删除");
	}
}

创建代理类 CglibProxy,该代理类需要实现 MethodInterceptor 接口,并实现接口中的 intercept()方法,
首先创建了一个动态类对象Enhancer,它是CGL旧的核心类;然后 调用了Enhancer类的 setSuperclass()方法来确定目标对象;接下来调用了 setCallback()方法添加回调函数,其中的 this 代表的就是代理类CglibProxy本身;最后通过 return语句将创建的代理类对象返 回。 intercept()方法会在程序执行目标方法时被调用,方法运行时将会执行切面类中的增强方法。

package Cglib代理;

import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.MethodInterceptor;
import jdk动态代理.MyAspect;

public class CglibProxy implements MethodInterceptor { // 创建代理类

	public Object createProxy(Object target) {// 代理方法
		// 创建一个动态类对象
		Enhancer enhancer = new Enhancer();
		// 确定需要增强的类,设置其父类
		enhancer.setSuperclass(target.getClass());
		// 添加回调函数
		enhancer.setCallback(this);
		// 返回创建的代理类
		return enhancer.create();
	}
	
	@Override
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		// 创建切面类对象
		MyAspect myAspect = new MyAspect();
		// 前增强
		myAspect.check_Permissions();
		// 目标方法执行
		Object obj = methodProxy.invokeSuper(proxy, args);
		// 后增强
		myAspect.log();
		return obj;
	}
}

创建测试类CglibTest。在该类的main()方法中首先创建代 理对象和目标对象,然后从代理对象中获得增强后的目标对象,最后调用对象的添加和删除方法,

package Cglib代理;
public class CglibTest {
	public static void main(String[] args) {
		CglibProxy cglibproxy = new CglibProxy();
		// 创建目标对象
		UserDao userDao = new UserDao();
		// 从代理对象中获取增强后的日标对象
		UserDao userDao1 = (UserDao) cglibproxy.createProxy(userDao);
		userDao1.addUser();
		userDao1.deleteUser();
	}
}

发布了285 篇原创文章 · 获赞 39 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_44973159/article/details/104918124