spring 动态代理

Java-基础 专栏收录该内容
26 篇文章 0 订阅

概括:

spring aop的实现原理:
    动态代理
    cglib代理


动态代理


代理模式:
    静态代理
    动态代理


(Spring如果发现被代理的类有接口的话,就用动态代理,否则用cglib)

动态代理 反射

JAVA的动态代理

  代理模式

    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

按照代理的创建时期,代理类可以分为两种。

    静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

    动态代理:在程序运行时,运用反射机制动态创建而成。


主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。


在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

Proxy这个类的作用就是用来动态创建一个代理对象的类它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法。


- 创建被代理的类以及接口。
- 创建一个实现接口InvocationHandler的类,他必须实现invoke方法
- 通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)创建一个代理
- 通过代理调用方法。


接口

 建实现类

 注意没用动态代理前,要想实现事务管理,需要在每个方法前后加上事务代码:

 

使用动态代理技术对这个实现类进行代理,来增强实现类里面的方法,例如把事务的代码插入到放到方法中。

import java.lang.reflect.Proxy;

public class UserServiceProxyFactory implements InvocationHandler {
	public UserService getUserServiceProxy() {
		//要执行的方法所在的对象
		private UserService us;
		public UserServiceProxyFactory(UserService us) {
			super();
			this.us = us;
		}
		//生成动态代理
		UserService usProxy = (UserService)Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
								UserServiceImpl.class.getInterfaces(),
								this)
		/*public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
		loader:类加载器,随便给一个
		interfaces:被代理对象的实现的接口
		h:这次代理要增强的内容,此处传一个InvocationHandler接口*/
		//返回
		return usProxy;
	}
	@Override
	public Object invoke() {
		Object invoke(Object proxy, Method method, Object[] args) {
			System.out.println("模拟打开事务");  //增强代码
			Object invoke = method.invoke(us, args);  //原有方法的调用,业务执行代码
			System.out.println("模拟提交事务");  //增强代码
			return invoke;
		}
		/*Object invoke(Object proxy, Method method, Object[] args) throws Throwable
		proxy:当前的代理对象
		method:当前调用的方法
		args:当前方法执行时的参数*/
	}
}

 

  • 5
    点赞
  • 0
    评论
  • 17
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值