2021-08-31 Aop的Jdk动态代理、CGLIB代理

Aop(Aspect-Oriented Programming),即面向切面编程。

Aspect:封装用于横向插入的系统功能(如:事务、日志等)类

Joinpoint:在程序执行过程中的某个阶段点

Pointcut:切面与程序流程的交叉点,即那些需要处理的连接点

Advice(通知/增强处理):在切点出所要执行的代码

Target Object(目标对象):指所有被通知/增强的对象

Proxy(代理):将通知应用到目标对象后,被动态创建的对象

Weaving(织入):将切面代码插入到目表对象上,从而生成代理对象的过程

JDK动态代理(对接口代理): 

 第一步:创建UserDao接口

package com.itheima.jdk;

/**
 * 第一步:创建UserDao接口
*/
public interface UserDao {
	/*
	 * 在接口中定义两个方法
	*/
	public void addUser();
	public void deleteUser();
}

第二步:创建接口实现类,UserDaoImpl

package com.itheima.jdk;

public class UserDaoImpl implements UserDao {

	@Override
	public void addUser() {
		System.out.println("addUser添加用户...");

	}

	@Override
	public void deleteUser() {
		System.out.println("deleteUser删除用户...");

	}

}

第三步:定义切面MyAspect

package com.itheima.aspect;

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

第四步:创建代理类JdkProxy

package com.itheima.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.itheima.aspect.MyAspect;

/**
 * JDK代理类
*/

//创建代理类需要继承InvocationHandler
public class JdkProxy implements InvocationHandler {
	
	//第一步:声名目标类接口 
	private UserDao userDao;
	
	//第二步:创建代理方法
	public Object createProxy( UserDao userDao) {
		
		this.userDao=userDao;
		
		//1、类加载器
		ClassLoader classLoader = JdkProxy.class.getClassLoader();
		
		//2、被代理对象实现的所有接口
		//将所有接口传给clazz
		Class<?>[] clazz = userDao.getClass().getInterfaces();
		
		//3、使用代理类,进行增强,返回的是代理后的对象
		//return返回,进入invoke
		return Proxy.newProxyInstance(classLoader, clazz, this);
	}
	
	/*
	 *所有动态代理类的方法调用,都会交由invoke()方法去处理
	 *proxy被代理后的对象
	 *method将要被执行的方法信息(反射)
	 *args执行方法时需要的参数 
	*/
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		//1、声明切面
		MyAspect myAspect = new MyAspect();
		//2、调用切面的方法,前增强
		myAspect.check_Permissions();
		
		//3、在目标类上调用方法,并传入参数
		//调用目标类UserDaoImpl的addUser()方法
		Object obj= method.invoke(userDao, args);
		
		//后增强
		myAspect.log();
		return obj;
	}

} 

第五步:创建测试类

package com.itheima.jdk;

public class JdkTest {
	public static void main(String[] args) {
		//创建代理对象
		JdkProxy jdkProxy = new JdkProxy();
		//创建目标对象
		UserDao userDao = new UserDaoImpl();
		
		//从代理对象中获取增强后的目标对象
		UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
		
		//执行方法
		//执行方法进入JdkProxy(代理)类
		userDao1.addUser();
		userDao1.deleteUser();
	}

}

CGLIB代理(对类代理,不需定义接口):

第一步:创建UserDao类,定义addUser(){....}、deleteUser(){...}方法

package com.ithema.cglib;

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

}

第二步:创建MyAspect切面类

package com.ithema.aspect;

/**
 * 切面类
*/
public class MyAspect {
	
	public void check_Permissions() {
		
		System.out.println("前增强....check_Permissions");
	}
	
	public void log() {
		
		System.out.println("后增强....记录日志log");
		
	}

}

第三步:创建CglibProxy代理类

package com.ithema.cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.ithema.aspect.MyAspect;

/*
 * CglibProxy代理类
*/

//使用jdk动态代理需要则需要继承InvocationHandler

//创建CglibProxy代理类,需要继承spring包中的,MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {
	
	
	/*
	 * jdk代理第一步:声明目标类接口private UserDao userDao;
	 * 第二步:创建代理方法
	 * 在代理方法中,需要将外部传入的userDao赋值给this.userDao
	 * 然后:
	 * 1、创建类加载器ClassLoader classLoader = JdkProxy.class.getClassLoader();
	 * 2、被代理对象实现接口Class<?>[] clazz = userDao.getClass().getInterfaces();
	 * 3、使用代理类,返回代理后对象return Proxy.newProxyInstance(classLoader, clazz, this);
	*/
	
	//cglib第一步:创建代理方法
	public Object createProxy(Object target) {
		
		
		//创建一个动态类对象
		Enhancer enhancer = new Enhancer();
		
		/*
		 * 确定需要增强的类,设置其父类
		*/
		enhancer.setSuperclass(target.getClass());
		//添加回调函数
		enhancer.setCallback(this);
		//返回创建的代理类
		
		return enhancer.create();
	}
	
	/**
	 * proxy Cglib根据指定父类生成的代理对象
	 * method拦截的方法
	 * args拦截方法的参数数组
	 * methodProxy方法的代理对象,用于执行父类的方法
	*/
	
	@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;
	}

}

第四步:创建测试类

package com.ithema.cglib;

public class CglibTest {

	public static void main(String[] args) {
		
		
		//1、创建代理对象
		CglibProxy cglibProxy = new CglibProxy();
		//2、创建目标对象
		UserDao userDao = new UserDao();
		//3、获取增强后的目标对象
		UserDao userDao2 = (UserDao) cglibProxy.createProxy(userDao);
		//4、执行方法
		userDao2.addUser();
		userDao2.deleteUser();
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值