对象增强方式之动态代理

原创 2018年04月15日 21:28:01

1.什么是动态代理

        什么代理,这个我在这里就不多说了,此类文章很多,读者一搜就有,如果在这里在写一遍就有点浪费时间了。那么说一下什么是动态代理,就是可以在程序运行的过程中,动态的创建的对象与方法,也就是说在运行之前是没有.class文件让你读入内存,然后创建对象,而是在运行的过程中在内存中创建对象,所以其具有更好的灵活性,为什么具有更好的灵活性请参见我的另一篇文章对象增强方式之装饰者模式。

  2.动态代理的特点:

        2.1、增强的内容是可以修改的,2.2、被增强的对象也是可以切换的。

3.为什么学习动态代理

    学习动态代理有助于我们更加深入的理解框架,特别是spring的面向切面编程AOP,当然不懂动态代理也可以使用框架,可是理解了动态代理,就可以轻松的理解框架的用法的含义。

4.学习动态代理需要哪些东西?

        答案是只有一个方法就够了!!,而这个方法就是newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);这个方法是Proxy类的一个方法。此方法的作用是:在运行时,动态创建一组指定的接口的实现类对象!

5.newProxyInstance方法的解释

    Object proxy = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler h);这几个参数的意义;

            ClassLoader:类加载器 把.class文件加载到内存,形成Class对象,不懂类加载器可以参见我的另一篇文章java的类加载器和Tomcat的类加载器
            2. Class[] interfaces:指定要实现的接口,可以是多个接口,因为是数组,哈哈。

            3. InvocationHandler:代理对象调用实现接口的所有方法,都会调用InvocationHandler的invoke()方法。

    举个栗子:

        

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

import org.junit.Test;

public class ProxyTest {
	@Test
	public void test1(){
		ClassLoader loader = this.getClass().getClassLoader();
		Class[] interfaces = {A.class,B.class};
		Object o = Proxy.newProxyInstance(loader, interfaces, new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				System.out.println("hello 动态代理");
				return null;
			}
			
		});
		A a = (A)o;
		a.aaa();
		a.bbb();
		B b = (B)o;
		b.ccc();
		b.ddd();
	}
}
interface A{
	public void aaa();
	public void bbb();
}
interface B{
	public void ccc();
	public void ddd();
}

执行结果为

    

hello 动态代理
hello 动态代理
hello 动态代理
hello 动态代理

这说明代理对象调用所实现接口的方法都会执行InvocationHandler的invoke()方法。

其实这invoke方法的三个参数是与代理对象方法一一对应的,接下来一张图来解释

    

b就对应于proxy这个代理,ccc方法对应于method ,参数对应于args,当然这个方法没有参数,举得不恰当了,哈哈

6.实现动态增强一个对象

        说了这么多都是在解释这个方法的含义,那么现实中它到底怎么用呢,这就通过一段代码来解释一下,

首先创建一个两个接口,来代表增强点

    

public interface BeforeStrengthen {//前置增强
	public void before();
}
public interface AfterStrengthen {//后置增强
	public void after();
}

然后创建一个工厂类,专门负责给对象增强,和得到代理对象

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

public class ProxyFactory {
	private Object targetObject;//目标对象
	private BeforeStrengthen beforeStrengthen;//前置增强
	private AfterStrengthen afterStrengthen;//后置增强
	private String strengthenMethod;//增强点
	
	
	/**
	 * 用来生成代理对象
	 * @return
	 */
	public Object createProxy() {
		ClassLoader loader = this.getClass().getClassLoader();
		Class[] interfaces = targetObject.getClass().getInterfaces();
		InvocationHandler h = new InvocationHandler() {

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				Object result = null;
				if(method.getName().equals(strengthenMethod)){
					// 执行前置增强
					if(beforeStrengthen != null) {
						beforeStrengthen.before();
					}
					
					result = method.invoke(targetObject, args);//执行目标对象的目标方法
					// 执行后置增强
					if(afterStrengthen != null) {
						afterStrengthen.after();
					}
					
				}else{
					result = method.invoke(targetObject, args);//执行目标对象的目标方法
				}
				
				// 返回目标对象的返回值
				return result;
			}
		
		};
		/*
		 *  得到代理对象
		 */
		Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
		return proxyObject;
	}
	
	//get和set方法
	public Object getTargetObject() {
		return targetObject;
	}
	public void setTargetObject(Object targetObject) {
		this.targetObject = targetObject;
	}
	public BeforeStrengthen getBeforeStrengthen() {
		return beforeStrengthen;
	}
	public void setBeforeStrengthen(BeforeStrengthen beforeStrengthen) {
		this.beforeStrengthen = beforeStrengthen;
	}
	public AfterStrengthen getAfterStrengthen() {
		return afterStrengthen;
	}
	public void setAfterStrengthen(AfterStrengthen afterStrengthen) {
		this.afterStrengthen = afterStrengthen;
	}


	public String getStrengthenMethod() {
		return strengthenMethod;
	}


	public void setStrengthenMethod(String strengthenMethod) {
		this.strengthenMethod = strengthenMethod;
	}
	
	
}

最后测试:

    

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

import org.junit.Test;

public class ProxyTest {
	@Test
	public void test2(){
		ProxyFactory factory = new ProxyFactory();//创建工厂
		factory.setTargetObject(new C());//设置目标对象
		factory.setBeforeStrengthen(new BeforeStrengthen(){//设置前置增强

			@Override
			public void before() {
				// TODO Auto-generated method stub
				System.out.println("前置增强");
			}
			
		});
		
		factory.setAfterStrengthen(new AfterStrengthen() {//设置后置增强
			public void after() {
				System.out.println("后置增强");
			}
		});
		factory.setStrengthenMethod("aaa");
		A a = (A)factory.createProxy();
		a.aaa();
		System.out.println("===================================");
		a.bbb();
	}
	
interface A{
	public void aaa();
	public void bbb();
}
class C implements A{

	@Override
	public void aaa() {
		System.out.println("我是AAAAA啊");
	}

	@Override
	public void bbb() {
		System.out.println("我是BBBBB啊");
	}
	
}

执行结果

前置增强
我是AAAAA啊
后置增强
===================================
我是BBBBB啊
以上代码就是给我们指定的对象的某一个方法增强了,不知道大家有没有懂呢?如果没懂参见我的另一篇文章对象增强方式之装饰者模式,说不定会有一些启示呢!如果我有不正确的地方,请批评指正

    






    

    





版权声明:本文为博主原创文章,未经博主允许不得转载。 如果转载,需要获得作者授权。保留追究法律责任的权力 https://blog.csdn.net/swf_shixinshou/article/details/79952421

深入Javascript Object(对象)视频教程

掌握Object的静态属性和静态方法, 原型属性和原型方法. 理解相关面向对象的一些使用方法等等. 为学习面向对象做一定的基础.
  • 2017年02月26日 13:00

利用动态代理模式来增强方法

在使用装饰着模式去增强某个类的时候会发现当被增强的那个类所实现的接口中含有的方法有很多个时,我们就需要将全部的方法都进行重写,显然这是不符合开发的习惯的,那有没有一种方式可以之增强我们需要的那个方法呢...
  • haofeijina
  • haofeijina
  • 2016-09-28 18:31:56
  • 789

增强 修改对象的集中方法(继承、装饰者模式、动态代理)

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflec...
  • qqahanson
  • qqahanson
  • 2014-12-11 09:45:41
  • 909

AOP动态代理对象的两种方式

在做权限控制的时候,需要有粗粒度和细粒度的权限控制,对于细粒度的程度,一般是对方法进行拦截,在调用方法的时候,对用户进行检查是否有权限,如果有权限则调用,否则不能调用。1.首先定义接口package ...
  • zxdu721
  • zxdu721
  • 2011-05-12 17:10:00
  • 1503

采用动态代理的方式对一个类进行增强

创建一个接口 package com.itheima.proxy; /* * 服务员的接口 */ public interface Waiter { public void server()...
  • call_me_back
  • call_me_back
  • 2017-11-09 23:26:09
  • 158

动态代理解决中文乱码

1.增强一个类的手段:1、继承 a) 优点简单 b) 必须有被增强类的实现类 2、装饰者模式 a) 要求:1实现相同的接口。2持有被增强的对象 b) 优点:不必知道被增强的实现是谁 ...
  • hr963171814
  • hr963171814
  • 2016-12-17 21:20:52
  • 756

代理模式--静态代理VS动态代理

代理模式: 作用:为目标对象提供一个代理对象以控制对目标对象的访问。 说明:代理对象存在的价值:主要用于拦截对真实业务对象(目标对象)的访问 应用:拦截器等 静态代理: 代理类和目标类必须实...
  • A__17
  • A__17
  • 2015-09-24 14:48:15
  • 471

动态代理的几种方式

AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执...
  • Happy_wu
  • Happy_wu
  • 2017-12-19 14:34:33
  • 7402

Java字节码的动态生成和增强

Java字节码的动态生成      实例         package test; import java.lang.reflect.Method; import java.ne...
  • Tibib
  • Tibib
  • 2013-01-11 10:28:21
  • 2609

两种动态代理的实现方式

最近浏览招聘信息,看到部分企业提到个人博客。我没有写博客的习惯,实话来说,我根本就没想到写博客。可能是我涉行不深,没有养成这种观念。看到很多大神都有自己的博客,里面各色各样的技术文章。让我非常向往。为...
  • u010887522
  • u010887522
  • 2015-03-17 17:05:50
  • 489
收藏助手
不良信息举报
您举报文章:对象增强方式之动态代理
举报原因:
原因补充:

(最多只允许输入30个字)