Spring框架 (13) —— 使用JDK动态代理

使用JDK动态代理

JDK动态代理是Java官方的代理

使用JDK官方的Proxy类创建代理对象

  1. 需要通过Proxy类创建代理对象
  2. 创建代理对象必须要一个代理处理类(实现了接口InvocationHandler的类)

JDK动态代理API分析

1、java.lang.reflect.Proxy 类:
Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
主要方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler hanlder)
方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例
参数:
loader :类加载器
interfaces : 模拟的接口
hanlder :代理执行处理器

返回:动态生成的代理对象

2、java.lang.reflect.InvocationHandler接口:
public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用
参数:
proxy :生成的代理对象
method :当前调用的真实方法对象
args :当前调用方法的实参

返回: 真实方法的返回结果
------------------------------------------------------------------------------------
jdk动态代理操作步骤
① 实现InvocationHandler接口,创建自己增强代码的处理器。
② 给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象。
③ 在处理器中实现增强操作。

案例代码

在我们的UserServiceImpl的实现类中,使用JDK的动态代理,进行方法的增强,增强事物的功能

JDK动态代理类

public class DynamicProxyHandler {
	//被代理的对象
	private Object target;
	//事务管理器
	private TransactionManagerHandler txManager; 
	/**
	 * 返回一个代理对象,代理对象就做了方法的增强,(事物管理,日志控制,权限管理等等)
	 */
	public <T> T getProxyObject(Class<T> clz) {
	
		/*
		 * JDK内置有一个代理类,专门负责创建动态代理对象的,类
		 * Proxy 类 , Proxy为被代理的对象创建代理对象
		 *   理论上创建被代理对象,是需要被代理对象的类对应的字节码的
		 * Proxy 在JVM动态的创建被代理对象的字节码,冬天的创建代理对象
		 */
		
		/*
		 * loader: 类加载器,类加载器就是从当前classpath下面加载字节码,在整个应用有且只有一个类加载器
		 * 		如何或者类加载器,
		 * 		方式一: 使用当前线程
		 *      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		 *     	 方式二: 使用任何一个类的字节码
		 *      target.getClass().getClassLoader()
		 * interfaces : 被代理对象的接口
		 * h : 处理器: 真正做代码增强的地方
		 */
		//代理对象
		Object newProxyInstance = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
			/**
			 * 代理内的增强方法,正常增强的地方
			 * @param proxy 代理对象
			 * @param method 被代理对象的方法
			 * @param args 被代理对象方法的参数
			 * @return  被代理对象执行的结果
			 * @throws Throwable
			 */

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//执行被代理对象的方法
				Object result = null;
				try {
					//方法之前执行操作
					//开始事务
					txManager.begin();
					result = method.invoke(target, args);
					//方法之后执行操作
					//提交事物
					txManager.commit();
				} catch (Exception e) {
					//回滚事物
					txManager.rollback();
				}finally {
					txManager.close();
				}
				return result;
			}
		});
		
		//返回代理对象
		return (T) newProxyInstance;
	}

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

	public void setTxManager(TransactionManagerHandler txManager) {
		this.txManager = txManager;
	}
}

配置文件

<!-- 配置事物管理器 -->
    <bean id="txMananger" class="cn.xc.spring.TransactionManagerHandler"/>
    
    
    <!-- 配置动态代理类 -->
	<bean id="dynamicProxy" class="cn.xc.spring.proxy.DynamicProxyHandler">
		<!-- 注入事物管理器 -->
		<property name="txManager" ref="txMananger"/>
		
		<!-- 配置被代理对象 -->
		<property name="target">
			<bean class="cn.xc.spring.service.impl.UserServiceImpl"/>
		</property>
	</bean>    

测试代码

@RunWith(SpringJUnit4ClassRunner.class) // 表示先启动Spring容器,把junit运行在Spring容器中
@ContextConfiguration("classpath:applicationContext.xml") // 读取Spring的配置文件
public class DynamicProxyTest {
	// 自动注入 UserService
	@Autowired
	private DynamicProxyHandler proxy;

	@Test
	public void testInsert() throws Exception {

		// 获取代理类对象的中的获取动态代理对象的方法
		UserService proxyObject = proxy.getProxyObject(UserServiceImpl.class);
		proxyObject.insert("张三");
	}
	@Test
	public void testUpdate() throws Exception {
		// 获取代理类对象的中的获取动态代理对象的方法
		UserService proxyObject = proxy.getProxyObject(UserServiceImpl.class);
		proxyObject.update("李四");
	}
}

JDK动态代理的不足

1,JDK动态代理的对象必须要实现一个接口;-因为JDK动态代理是基于接口代理的
2,需要为每个对象创建代理对象;
3,动态代理的最小单位是类(所有类中的方法都会被处理),查询方法不需要事务,可能不需要被代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值