Spring——JDK动态代理

一.动态代理

1.简介

  • JDK动态代理的实现是在运行时,根据一组接口定义,使用Proxy、InvocationHandler等工具类去生成一个代理类和代理类实例。
  • 需要建一个拦截器实现InvocationHandler接口重写invoke方法用来拦截并执行目标类业务
  • 在拦截器里面提供有参构造函数,里面传入Object目标类和所有切面类对象
  • 可以通过在拦截器里面增加切面类来增加功能(通知)
  • 测试类里面Proxy.newProxyInstance(目标类加载器,目标类接口,拦截器)获得的就是和UserDaoImpl一样的UserDao代理对象

2.注意事项

  • Jdk产生动态代理目标类UserDao必须实现一个接口UserImpl
  • Jdk产生动态代理必须创建一个拦截器MyInterceptor,继承InvocationHandler接口,重写invoke方法来融合目标类和事务类,method.invoke(target,args)来调用目标类方法
  • 代理类中使用JDK创建代理对象,Proxy.newProxyInstance(目标类,目标类接口,拦截器);
  • 代理类的是作用是融合目标类方法和各种通知方法的集合
  • 所有事务类里面的方法都叫通知,目标类方法前面执行的叫前置通知,目标类后面的叫后置通知
  • 代理对象调用save方法,首先走的是拦截器里面的invoke方法

2.理解

在这里插入图片描述
在这里插入图片描述

3.好处

目标类和事务类互相独立,降低耦合性和侵入性。

4.区别

JDK和Cglib的区别

二.代码

1.目标类接口

package com.jp.dao;
import com.jp.domain.User;

public interface UserDao {
	void save(User user);
}

2.目标类(客户)

package com.jp.dao;
import com.jp.domain.User;

public class UserDaoImpl implements UserDao {

	@Override
	public void save(User user) {
		//开启事务
		//日志记录
		//安全校验
		System.out.println("保存用户成功");
		//提交事务
	}
}

3.事务类

package com.jp.transcation;

public class MyTranscation {
	public void begin(){
		System.out.println("开启事务");
	}
	public void commit(){
		System.out.println("提交事务");
	}
}
package com.jp.transcation;

public class Loggle {
	public void log(){
		System.out.println("日志记录");
	}
}
package com.jp.transcation;

public class Security {
	public void safe(){
		System.out.println("安全校验");
	}
}

4.拦截器

继承InvocationHandler接口,实现invoke方法

package com.jp.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.jp.transcation.Loggle;
import com.jp.transcation.MyTranscation;
import com.jp.transcation.Security;

public class MyInterceptor implements InvocationHandler{
	private Object target;					//目标类UserDaoImpl
	private MyTranscation myTranscation;	//事务类(切面)
	private Loggle log;						//日志类
	private Security security;				//安全校验类
	//有参构造
	public MyInterceptor(Object target, MyTranscation myTranscation,Loggle log, Security security) {
		super();
		this.target = target;
		this.myTranscation = myTranscation;
		this.log = log;
		this.security = security;
	}
	//proxy是代理类对象,method封装目标类的方法,args是目标类的参数
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
		myTranscation.begin();		//开启事务
		log.log();					//日志记录
		security.safe();			//安全校验
		method.invoke(target, args);//调用目标类方法
		myTranscation.commit();		//提交事务
		return null;
	}
}

5.测试类

package com.jp.test;

import java.lang.reflect.Proxy;
import com.jp.dao.UserDao;
import com.jp.dao.UserDaoImpl;
import com.jp.domain.User;
import com.jp.jdkproxy.MyInterceptor;
import com.jp.transcation.Loggle;
import com.jp.transcation.MyTranscation;
import com.jp.transcation.Security;

public class JdkProxyTest {
	public static void main(String[] args) {
		//创建目标对象
		UserDao userDao=new UserDaoImpl();
		//创建事务对象
		MyTranscation myTranscation=new MyTranscation();
		//创建日志对象
		Loggle log=new Loggle();
		//创建安全校验对象
		Security security=new Security();
		//创建拦截器对象
		MyInterceptor myInterceptor=new MyInterceptor(userDao,myTranscation,log,security);
		//JDK帮忙创建代理对象
		//代理类将目标类和事务类通过拦截器的invoke方法融合到一起
		//第一个参数:目标类加载器.第二个参数:获得目标类的所有接口.第三个参数:拦截器
		UserDao userDaoProxy = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), myInterceptor);
		User user=new User();
		
		//代理对象调用save方法,首先走的是拦截器里面的invoke方法
		userDaoProxy.save(user);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值