jdk动态代理实现过程,及spring中AOP和事务控制的原理应用讲解

15 篇文章 0 订阅
2 篇文章 0 订阅

jdk动态代理

好处在于我们可以把功能性的代码实现更好的封装把公共性的代码抽取出来由代理类去完成。

被代理实体只注重关键功能的实现,好处在于同一类业务的所有类,都可以交由代理类去代理我们只需要注重关键代码的开发(例如日志,事务回滚)。
注意:jdk动态代理类是基于接口生成的,所以说我们的被代理实体必须要继承一个接口

原生的jdk实现动态代理的代码实现:

编写被代理类接口

public interface student_interface {
	public void add();

	public void update();

	public void delete();
}

编写被代理实现类

public class studentImp implements student_interface {
	@Override
	public void add() {
		System.out.println("添加学生");
	}

	@Override
	public void update() {
		System.out.println("更新学生");
	}

	@Override
	public void delete() {
		System.out.println("删除学生");
	}
}

编写代理句柄类

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

public class ProxyHandle implements InvocationHandler {
	private Object target;

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	/**
	 * 获得动态代理类,由proxy类封装好的方法获得,返回是一个代理实例
	 * 
	 * @return
	 */
	public Object getproxy() {
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable // 该方法被代理类调用
	{
		System.out.println("前置操作:Do something");
		Object result = method.invoke(target, args); // 执行被代理类相对应的方法,args是参数 method是方法名,即调用target.method(args)
		System.out.println("后置操作:Do something");
		return result;
	}
}


测试类

public class Client {
	public static void main(String[] args) {
		//1 :创建一个代理句柄
		//2 :创建一个被代理实例
		ProxyHandle pih = new ProxyHandle(); // 创建代理句柄
		//3:将被代理实例向代理句柄注册
		pih.setTarget(new studentImp()); // 设置被代理类
		//4 :得到代理类
		student_interface proxy = (student_interface) pih.getproxy(); // 获取代理类
		System.out.println(proxy.getClass().getName());// 返回对象名以$Proxy0结尾
		//5 :通过代理类调用相应的方法
		proxy.add(); // 会调用pih的invoke方法,invoke方法又调用被代理实体的对应方法
	}
}

总结

返回的代理类是一个由jdk的proxy类动态的创建的实例,我们不需要去重复的去为每一个被代理类,写不同的代理实例相同的业务逻辑只需要写一个代理句柄通过代理句柄获得代理实例,然后在invoke方法中写你的前置后置操作

原理

getproxy方法根据你传入的被代理类,实现的接口动态的生成一个代理类,代理类中所有的方法体其实都是调用 invoke()这个方法。

而invoke方法中你可以自定义你的前置操作和后置操作。所以具有相同业务逻辑的业务执行流程可以封装被代理类的invoke方法中。

所以说我们同时在内存中创建了三个对象代理类句柄类生成代理类,且invoke方法供代理类调用),代理类被代理类

spring中的实际应用

spring中AOP事务控制的原理都是基于动态代理来实现的spring中动态代理的模式有两种:jdk动态代理cglib动态代理

Spring AOP的代理

Spring AOP中的代理使用的默认策略是:
如果目标对象实现了接口,则默认采用JDK动态代理
如果目标对象没有实现接口,则采用CgLib进行动态代理
如果目标对象实现了接口,且强制CgLib代理,则采用CgLib进行动态代理

JDK动态代理和CgLib动态代理的主要区别

  1. JDK动态代理只能针对实现了接口的类接口方法进行代理
  2. CgLib动态代理基于继承来实现代理,所以无法对final类private方法static方法实现代理

在于cglib的被代理类不需要继承接口,他可以直接根据类生成代理类

  • aop中我们可以把切点看作是被代理的具体方法
  • 切面就是上述说的前置后置操作

spring的事务反转

至于spring的事务反转,它的原理是捕获异常时进行rollback,我们可以想象成用try-catch将被代理方法包裹起来,一旦捕获异常进行数据回滚并将异常往controller抛出但是在回滚时默认只会捕获RuntimeException因为mybatis抛出的异常是运行时异常,如果要指定其他异常也回滚的话注解标签添加@Transactional(rollbackFor = Exception.class) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿啄debugIT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值