代理类

c# Webservice 生成代理类并在客户端调用 声明:我用此方法成功生成了一个代理类 并且成功实现了功能,有遇到类似问题没解决的 可以留言给我  我也是菜鸟 互相学习 互相进步 生成: VS(2005/2008都可以)命令: 开始》运行》CMD C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin>wsdl /language:c# /n:XYS.MISS.Photo.Ph 阅读详情

一、程序中的代理原理


(一)要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、食物管理、等等

(二)编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

class X{

              void sayHello(){

                            System.out.println("hello,itcast");

              }

}

要在sayHello方法上增加一个统计执行这个方法需要时间的功能,前提是上边的类的源代码没有给,

做一个X的代理,

XProxy

{

  void sayHello(){//既然是代理,就有相同的方法声明

starttime

X.sayHello();

endtime

}

}

之后就可以调用XProxy



代理架构图


1、客户端原来调用的是Target,现在然客户端调用代理。代理和目标是实现了相同的接口doSomeThing(),也就是说对外有相同的方法,

         例如用Collection引用HashSet,Collection引用ArrayList

String className=props.getProperty("className");
Collection collections=(Collection)Class.forName(className).newInstance();//得到了类.调用不带参数的构造方法

                Collection引用一个集合(Collection),Collection是一个接口,他会引用HashSet,也会引用ArrayList,但在源程序里面没出现这两个类的名字,只出现了接口,这样                    就可以切换,不用改源代码就可以切换

2、在代理的方法里,一定要调用目标的对应的方法,但是在调用目标的方法的前边或者后边会加上一点系统功能代码,

类图:虚线表示实现接口

(三)工厂模式和配置文件的方式进行管理

则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换。

例如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易

配置文件config.properties

中配置,到底用哪个类className=java.util.HashSet;

二、AOP  交叉业务的编程问题即为面向方面的编程(Aspect oriented program)

面向代理的编程现在应用很广

(一)系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面

例如:

        类StudentService负责对学生进行管理,增删改查

类CourseService负责对课程进行管理,管理课程的增删改查

类MiscService对其他信息进行管理,例如管理老师的信息,教室的信息,

但不管什么类,里面都要有安全、事务、日志等功能,贯穿了好些模块当中去了,所以他们就成了交叉业务,他们好像不是一个独立的对象,

(二)用具体的程序代码描述交叉业务:

method1            method2         method3

{ {{

-------------------------------------------------------切面  安全、事务....功能

-------------------------------------------------------切面  安全、日志.....功能

} } }

一个问题域、一个面,变这样的程序就称之为AOP(面向方面的编程)

(三)交叉业务的编程问题即为面向方面的编程(Aspect oriented program)的目的就是要把交叉业务模块化

就是把交叉业务贯穿到好些业务模块中了,把这样的东西模块化,只写一份,其他的全自动应用上,而不是在每个地方都去写,写的时候就用代理的方法

我们不可能去改变目标的方法或者不可能深入到目标的方法内部中去修改,但让用户感觉在方法前/后加了代码,于是把这段代码移到方法外面,,运行的效果与上面一样

-------------------------------------------------------切面

func1               func2         func3

{ {{

... ... ...

} } }

-------------------------------------------------------切面

(四)使用代理技术正好可以解决(三)的问题

三、动态代理技术

a、要为系统中各种借口的类增加代理功能,需要太多的代理类,都采用静态代理方式,会是一件非常麻烦的事

b、JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类

c、JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。

d、CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库

如果有一个目标类本身没有实现接口,那么生成代理类的方法要不要跟目标类的方法一模一样,就是声明了、定义一模一样,要!

而这个目标类没有实现接口,那我通过什么方式来告诉java虚拟机:你跟我生成的类跟那个类有相同的方法列表。Java虚拟机干不了这个事,因为这个目标类没有接口,无法跟java虚拟机说生成这个类的接口方法,没接口,这时候有一个第三方库:CGLIB

CGLIB库可以动态生成一个类的子类,这个子类跟你有没有相同的方法,他继承了父类的所有方法,还不等于有父类方法的声明么,要有CGLIB库才可以生成没有接口的类的子类,现在CGLIB库不是sun公司的,是一个开源的

e、我们生成的目标,生成的代理的方法,去调用目标相应的方法,除了调用目标的方法,还干些额外的事:如果这个代理什么都不干,只是调用目标的方法这个代理就没什么价值,于是可以做些额外的事情

在代理方法中的位置加上系统功能代码:

1、在调用目标方法之前  2、在调用目标方法之后  3、在调用目标方法前后  4、在处理目标方法异常的catch块中

(一)分析JVM动态生成的类

1、用jdk Java虚拟机自己提供的API来生成动态类,用Java虚拟机API生成动态类一定要告诉他一个接口,

2、用的API为java.lang.reflect.Proxy:有个方法(getProxyClass(ClassLoader loader,Class<?>... interfacess),这个方法返回的是class字节码【 static Class<?>】),也就是在内存中造出了一个字节码,也就是说给你造出一个类。

         但是在早字节码的时候,需要告诉他这个字节码实现了哪些接口(Class<?>... interfacess);

         另外还有一个ClassLoader,我们每一个字class,就每一个字节码都能getClassLoader可以得到自己的类加载器,也就是说每一个Class一定是由一个类加载器加载进来的,就好比每一个人一定有一个妈妈,如果没有妈妈逻辑不通。可是。在java虚拟机内存里面操作一个字节码没有ClassLoader,没有通过类加载器加载,可是也要给他指定一个类加载器,所以创建时一定要指定一个类加载器,做一个动态类:


StringBuilder与StringBuffered的区别:

他们在运用上基本上一样,都是动态的往字符串上添加内容

在单线程里面StringBuilder效率高一些,多线程的情况就要用StringBuffered

现在这个线程肯定被一个线程操作,因为这个线程没有被定义到类里面,被多个线程共享

    假设有5个线程调用main方法,那等于有5个main方法同时运行,
*     5个main方法同时运行就有5个StringBuilder变量,
*     个是个的变量,彼此不受影响
*     既然它不受别的线程影响,所以他就不用考虑安全的问题,不考虑安全,效率就高
*     如果此时用StringBuffered在这里,即使不受其他线程的影响,它还要考虑安全,这样效率就低
 

例:

			StringBuilder sBuilder=new StringBuilder(name);
			
			sBuilder.append('(');
			Class[] clazzParams=constructor.getParameterTypes();
			for (Class clazzParam:clazzParams) {
				sBuilder.append(clazzParam.getName()).append(',');
				
			}
			if (clazzParams!=null&&clazzParams.length==0) {
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			
			sBuilder.append(')');
			System.out.println(sBuilder.toString());


package cn.itcast.day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest {

	/**
	 * @param args
	 * @throws Exception 
	 * @throws  
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		/*
		 * 指定的接口是Collection
		 * 表达Collection这个接口其实就是用它的字节码Collection.class;
		 * 这个类加载器通常用接口相同的类加载器Collection.class.getClassLoader();
		 * 所以得到一个Class  clazzProxy1
		 * 一般看到变量前面前缀为clazz就要考虑变量为一个字节码 
		 * */
		Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		/*
		 * 既然clazzProxy1是一个字节码,就可以getName
		 * 打印,这个类的名字叫$Proxy0
		 */
		System.out.println(clazzProxy1.getName());
		
		System.out.println("-------------begin constructors list-------------");
		
		/*
		 * 既然是类的字节码,看看类的身上有什么构造方法,每个构造方法接受的参数类型是什么样
		 * 也看看这个类身上有什么方法
		 * a、类的身上有什么构造方法,Constructor代表方法,
		 * 要的到所有的构造方法肯定是一个数组
		 * 得到一个字节码clazzProxy1以后,可以clazzProxy1.getConstructors()
		 * 就可以得到constructor的名字、参数列表constructor.getName();
		 * 希望可以打印出来叫:$Proxy0(),不带参数构造方法是这样
		 * 假设还有一个参数          $Proxy0(InvocationHandler x,int)
		 * 这时两个构造方法,第一个无参,第二个有参,
		 * 希望把他们打印出来,变量的名字并不重要,只是打印参数的类型和个数,
		 * 想以这种列表的形式进行打印:$Proxy0(), $Proxy0(InvocationHandler x,int)
		 * 拼出这个串
		 * 
		 * 现在这个线程肯定被一个线程操作,因为这个线程没有被定义到类里面,被多个线程共享 
		 */
		
		Constructor[] constructors=clazzProxy1.getConstructors();
		for (Constructor constructor:constructors) {
			//得到名字constructor.getName();
			String name=constructor.getName();
			//拼出这个串,初始值为name,也就是说等于$Proxy0()这部分
			StringBuilder sBuilder=new StringBuilder(name);
			
			sBuilder.append('(');
			/*
			 * 在这里增加一对员工号就等于增加参数列表
			 * 
			 */
			Class[] clazzParams=constructor.getParameterTypes();//得到构造函数的参数类型
			for (Class clazzParam:clazzParams) {
				sBuilder.append(clazzParam.getName()).append(',');//有多个参数列表肯定有','.$Proxy0(InvocationHandler x,int)
				
			}
			if (clazzParams!=null&&clazzParams.length==0) {
				sBuilder.deleteCharAt(sBuilder.length()-1);//去掉最后一个','
			}
			
			sBuilder.append(')');
			System.out.println(sBuilder.toString());
		}
		
		
		System.out.print("-------------begin methods list-------------");
		
		Method[] methods=clazzProxy1.getMethods();
		for (Method method:methods) {
			String name=method.getName();
			StringBuilder sBuilder=new StringBuilder(name);
			
			sBuilder.append('(');
			Class[] clazzParams=method.getParameterTypes();
			for (Class clazzParam:clazzParams) {
				sBuilder.append(clazzParam.getName()).append(',');
				
			}
			if (clazzParams!=null&&clazzParams.length==0) {
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			
			sBuilder.append(')');
			System.out.println(sBuilder.toString());
		}
}

结果:

$Proxy0
-------------begin constructors list-------------
$Proxy0(java.lang.reflect.InvocationHandler)      //只有一个构造方法,并且要接收一个参数java.lang.reflect.参数的类型是 :InvocationHandler。生成的这个动态类有构造方//法,参数是InvocationHandler
-------------begin methods list-------------add(java.lang.Object)
hashCode)
clear)
equals(java.lang.Object,)
toString)
contains(java.lang.Object,)
isEmpty)
addAll(java.util.Collection,)
iterator)
size)
toArray([Ljava.lang.Object;,)
toArray)
remove(java.lang.Object,)
containsAll(java.util.Collection,)
removeAll(java.util.Collection,)
retainAll(java.util.Collection,)
isProxyClass(java.lang.Class,)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;,)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler,)
getInvocationHandler(java.lang.Object,)
wait)
wait(long,int,)
wait(long,)
getClass)
notify)
notifyAll)


3、创建动态类的实力对象及其调用方法

a、用反射获得构造方法

b、编写一个简单的InvlcationHandler类

c、调用构造方法传进动态类的实力对象,并将编写的InvlcationHandler类的实力对象穿进去

d、打印创建的对象和调用对象的没有返回值的方法和getClass方法演示调用其他有返回值的方法报告了异常。

e将创建动态类的实例对象的代理改成匿名内部类的形式编写,

package cn.itcast.day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest {

	/**
	 * @param args
	 * @throws Exception 
	 * @throws  
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub		
		Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);		
		System.out.println(clazzProxy1.getName());	
		System.out.println("-------------begin constructors list-------------");
		
		Constructor[] constructors=clazzProxy1.getConstructors();
		for (Constructor constructor:constructors) {
			//得到名字constructor.getName();
			String name=constructor.getName();
			//拼出这个串,初始值为name,也就是说等于$Proxy0()这部分
			StringBuilder sBuilder=new StringBuilder(name);
			
			sBuilder.append('(');
			/*
			 * 在这里增加一对员工号就等于增加参数列表
			 */
			Class[] clazzParams=constructor.getParameterTypes();//得到构造函数的参数类型
			for (Class clazzParam:clazzParams) {
				sBuilder.append(clazzParam.getName()).append(',');//有多个参数列表肯定有','.$Proxy0(InvocationHandler x,int)
			}
			if (clazzParams!=null&&clazzParams.length!=0) {
				sBuilder.deleteCharAt(sBuilder.length()-1);//去掉最后一个','
			}
			sBuilder.append(')');
			System.out.println(sBuilder.toString());
		}
		
		System.out.println("-----------begin create instance object-------");
		/*
		 * 上面得到了字节码clazzProxy1
		 * clazzProxy1.newInstance()是得到无参的构造方法
		 * clazzProxy1.getConstructor(参数类型):是得到有参的构造方法(用反射获得)
		 *      在获得构造方法时用到的是 参数类型
		 * 构造方法接受一个参数:InvocationHandler.class,在
		 * 调用构造方法创建对象的时候就要传真正的参数:
		 * 
		 * 
		 * InvocationHandler是一个接口,就没法new,只能new他的实现类
		 */
		Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
		
		//做个InvocationHandler的实现类MyInvocationHander1
		class MyInvocationHander1 implements InvocationHandler{

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}	
		}
		/*用构造方法constructor去newInstance,传递一个对象new MyInvocationHander1()。。
		  调用构造方法传进动态类的实力对象,并将编写的InvlcationHandler类的实力对象穿进去*/
		  Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHander1());
		/*
		 * 打印的结果为null:
		 * 说明有两种可能:
		 * 1、一种是proxy1没有创建成功为null
		 * 2、一种是proxy1的toString方法返回了null。
		 *     所以proxy1.toString()可能会报告空指针异常
		 *     打印以后有一个假象,也有可能是null,也有可能空指针返回null
		 */
		System.out.println(proxy1);
		proxy1.clear();//clear方法返回void,清除集合。如果此处不报告空指针异常肯定proxy1对象有了
//		proxy1.size();//size方法有返回值,返回的是invoke的返回值,是null,而size是整数型的,所以不能成功调用
		
}

4,动态类实际应用

方法二

		Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){//跟上面同样效果

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}});

Proxy的newProxyInstance(类加载器,接口,用字节码传递的实例对象)静态方法,机能有实力对象又能有字节码

注意:

  • Proxy 前的强制转换必须为接口,否则会出现                                                                                                                                                                              java.lang.ClassCastException:  $Proxy0 cannot be cast to 


Proxy 提供用于创建动态代理类和实例的静态方法.
newProxyInstance()
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
InvocationHandler 是代理实例的调用处理程序 实现的接口。
invoke()
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

		/*
		 * 类加载器就是接口的类加载器Collection.class.getClassLoader()
		 */
		Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				new Class[]{Collection.class},//接口,可能是一个也可能是多个
				new InvocationHandler(){

					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						ArrayList target=new ArrayList();//指定一个目标,每次调用add都要处理一次目标
						return method.invoke(target, args);
					}}
				);
		proxy3.add("zxx");
		proxy3.add("lhm");
		proxy3.add("bxd");
		System.out.println(proxy3.size());

结果:0


动态类生成的类的内部代码

1、动态类生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和一个如下接受InvocationHandler参数的构造方法。

2、构造方法接受一个InvocationHandler对象,接受对象了要干什么用呢?该方法内部的代码回事怎样的呢?

3、

                                Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				new Class[]{Collection.class},//接口,可能是一个也可能是多个
				new InvocationHandler(){
			  		ArrayList target=new ArrayList();//指定一个目标
					@Override
					/*
					 * invoke收到了客户端调用的三要素
					 * 现在还是调用方法method.invoke(target, args);
					 * 但是不是去调用代理对象,而是去调用目标,就是在目标身上在去执行刚才那个代理正在执行的方法
					 * 并且刚才代理传递的什么参数,继续把这个参数传递给目标的方法
					 * 目标执行完了返回一个值retVal
					 * 把这个值返回出去
					 * 代理的invoke方法就会受到这个返回值了
					 * invoke返回的结果就会返回给代理
					 * 代理proxy3调用add方法传递参数
					 * 代理add的返回值从invoke的返回值里面取
					 * 这样就把目标返回的结果返回到代理身上去了 
					 */
					public Object invoke(Object proxy, Method method,//proxy当前正在调用代理对象,method调用这个代理对象的哪个方法
							Object[] args) throws Throwable {//调用这个代理对象为它传递哪个参数
						
						//调用目标前可以加代码
						long beginTime=System.currentTimeMillis();
						
						//可以在调用目标之前,把参数args改一改。比如写个过滤器,对原来传进来的参数进行修改,返回的结果也可以修改,当改的类型一定要一致
						Object retVal=method.invoke(target, args);
						//调用目标后可以加代码
						long endTime=System.currentTimeMillis();
						System.out.println(method.getName()+"running time:"+(endTime-beginTime));
						return retVal;
					}}
				);
		//Handler()返回的结果给了add方法,add方法继续向外返回,Handler()返回的结果来源于目标返回,目标返回的结果交给invoke
		Object obj=proxy3.add("zxx");//调用代理的add方法
		proxy3.add("lhm");
		proxy3.add("bxd");
		System.out.println(proxy3.size());

		//Handler()返回的结果给了add方法,add方法继续向外返回,Handler()返回的结果来源于目标返回,目标返回的结果交给invoke
		Object obj=proxy3.add("zxx");//调用代理的add方法
		proxy3.add("lhm");
		proxy3.add("bxd");
		//System.out.println(proxy3.size());
		System.out.println(proxy3.getClass().getName());
结果:$Proxy0
因为:        getClass方法是从Object类继承过来的
   hashCode,equals,toString三个方法委托给handler,其他的都不委托


下面

* 要把代码参数的形式传进来,可以把这些代码写成字符串,然后放进来,执行这些字符串表示的代码,在java中sclipe有这种方法
* 传递一个字符串进来,执行eval代码,这样的好处是可以在运行的时候放进来
* 设计代码在程序运行时可以临时设置,而不是编译代码时提前指定好
* 传递个对象给InvocationHandler,
* 只要把想要执行的对象放到InvocationHandler方法里面
* 调用代码就等于执行所给的代码

重构方法,选中

Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), 
new Class[]{Collection.class},//接口,可能是一个也可能是多个
new InvocationHandler(){ 
@Override
public Object invoke(Object proxy, Method method,//proxy当前正在调用代理对象,method调用这个代理对象的哪个方法
Object[] args) throws Throwable {//调用这个代理对象为它传递哪个参数
long beginTime=System.currentTimeMillis();
Object retVal=method.invoke(target, args);
long endTime=System.currentTimeMillis();
System.out.println(method.getName() +"running time:"+(endTime-beginTime));
return retVal;
}}
);

右键Refactor->Extract Method,起名


定义一个接口,新建一个Advice.java文件(希望你执行的系统功能,也是别人对你的一个建议,即将插入进来的,嵌入进来的建议,像这种系统功能一般起名Advice)

在ProxyTest.java里加上

ProxyTest.java

advice.afterMethod();

                final ArrayList target=new ArrayList();//指定一个目标,把目标拿出来
		Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
                private static Object getProxy(final Object target,final Advice advice) {//target目标,advice系统功能。生成代理
		Object proxy3=Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
			/*	new Class[]{Collection.class},//接口,可能是一个也可能是多个*/
				target.getClass().getInterfaces(),//与target实现相同的接口
				new InvocationHandler(){
			  		
					@Override
					/*
					 * invoke收到了客户端调用的三要素
					 * 现在还是调用方法method.invoke(target, args);
					 * 但是不是去调用代理对象,而是去调用目标,就是在目标身上在去执行刚才那个代理正在执行的方法
					 * 并且刚才代理传递的什么参数,继续把这个参数传递给目标的方法
					 * 目标执行完了返回一个值retVal
					 * 把这个值返回出去
					 * 代理的invoke方法就会受到这个返回值了
					 * invoke返回的结果就会返回给代理
					 * 代理proxy3调用add方法传递参数
					 * 代理add的返回值从invoke的返回值里面取
					 * 这样就把目标返回的结果返回到代理身上去了
					 */
					public Object invoke(Object proxy, Method method,//proxy当前正在调用代理对象,method调用这个代理对象的哪个方法
							Object[] args) throws Throwable {//调用这个代理对象为它传递哪个参数
						
						/*//调用目标前可以加代码
						long beginTime=System.currentTimeMillis();
						
						//可以在调用目标之前,把参数args改一改。比如写个过滤器,对原来传进来的参数进行修改,返回的结果也可以修改,当改的类型一定要一致
						Object retVal=method.invoke(target, args);
						//调用目标后可以加代码
						//System系统功能抽取成对象
						long endTime=System.currentTimeMillis();
						System.out.println(method.getName() +"running time:"+(endTime-beginTime));
						return retVal;*/
						
						
						
						advice.beforeMethod(method);
						//可以在调用目标之前,把参数args改一改。比如写个过滤器,对原来传进来的参数进行修改,返回的结果也可以修改,当改的类型一定要一致
						Object retVal=method.invoke(target, args);
						//调用目标后可以加代码
						//System系统功能抽取成对象
						advice.afterMethod(method);
						return retVal;
					}}
				);
		return proxy3;
	}

Advice.java

package cn.itcast.day3;

import java.lang.reflect.Method;

/*
 * 一般有四种
 * 再异常里执行的方法
 * 在方法之前执行的
 * 在方法之后执行的
 * 在方法之前后执行的
 */
public interface Advice {
	public void beforeMethod(Method method);
	public void afterMethod(Method method);
}

MyAdvice.java

package cn.itcast.day3;

import java.lang.reflect.Method;

public class MyAdvice implements Advice {

	long beginTime=0;
	public void afterMethod(Method method) {
		// TODO Auto-generated method stub
		System.out.println("从传智播客毕业上班了");
		long endTime=System.currentTimeMillis();
		System.out.println(method.getName() +"running time:"+(endTime-beginTime));
		
	}

	
	public void beforeMethod(Method method) {
		// TODO Auto-generated method stub
		System.out.println("到传智播客学习");
		beginTime=System.currentTimeMillis();
	}

}
结果:

null
到传智播客学习
从传智播客毕业上班了
addrunning time:1
到传智播客学习
从传智播客毕业上班了
addrunning time:1
到传智播客学习
从传智播客毕业上班了
addrunning time:0
到传智播客学习
从传智播客毕业上班了
sizerunning time:0
3
$Proxy1

四、实现AOP功能的封装与配置

类似于spring的AOP框架

思路:

1、Object obj=BeanFactory.getBean("xxx")

工厂BeanFactory(产生javabean的factory),参数是Bean的名字,根据这个名字创建出javabean的对象,

a、BeanFactory的构造方法接受代表配置文件的输入流对象,配置文件格式如下:

xxx=java.util.ArrayList

xxx=cn.itcast.ProxyFactoryBean

xxx.target=java.util.ArrayList

xxx.advice=java.util.Myadvice

b、ProxyFacotryBean充当封装生成代理的工厂


创建工厂BeanFactory.java,专门创建javaBean对象,



C++ 实现代理类 定义: 定义一个行为和类的对象 阅读详情

相关推荐

【Java基础知识 27】Java代理类详解

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

学Java,找哪吒 8584

【黑马程序员】java中的--------------代理类与动态代理技术

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ---------------------- 一、代理的理解: 1、 生活中的代理;就好比我们买电脑,我们不必亲自去厂家购买,只有去代理商店去买就可以了,既方便,而且还可以享受代理商店的一些特有的服务。比如:厂家,代理商,客户这三者这间的关系客户买产 品并不直接与生产

u011079455的专栏 761

【QT】自定义代理类

本文介绍我们为什么要使用自定义代理类,结合例如在samp5_4的实例实现为TableView增加自定义代理组件功能。将QSpinBox、QDoubleSpinBox、QComboBox委托给模型来代理,就可以实现在TableView中添加控件进行交互了。

u011671745的博客 1801

java代理详解

代理模式:为其他对象提供一种代理以控制对这个对象的访问。

weixin_44713306的博客 1268

代理类在UI控件中的实践应用

在面向对象编程中,代理类是一种实现设计模式的技术,它允许在不直接修改原始对象的情况下,控制对它的访问。代理类作为抽象层,为其他对象提供了一个接口,可以在此基础上增加额外的行为,如权限验证、延迟加载、日志记录等。代理模式在软件开发中扮演着关键角色。首先,代理类可以用来增加代码的模块化和可读性。其次,它可以作为一种结构化工具,帮助开发者在复杂的系统中管理对象之间的交互。最后,代理类的使用使得系统更加灵活和易于维护。

weixin_33193177的博客 1002

新手必看:电路设计里的‘地’到底怎么接?单点、多点、混合接地保姆级图解

本文深入解析电路设计中的接地技术,涵盖单点、多点和混合接地的原理与应用。通过详细的图解和实战案例,帮助新手理解接地在提供参考电位、构成电流回路及抑制电磁干扰中的关键作用,避免常见设计误区,提升电路稳定性与抗干扰能力。

weixin_28455801的博客 300

代理(Proxy)

由代理类和被代理类组成,类似于经纪人和明星之间的关系,是否创建对象由代理类进行决定,代理类和被代理类必须实现同一个接口,调用代理类方法实现同名被代理类方法的执行,在运行期间进行创建动态一个总代理类,称为动态代理,通过反射进行。代理类是在程序的运行过程中动态创建的,一旦被创建,它们也就变成了常规类,与虚拟机的常规类没有什么区别。只要是代理模式的话必须要有一个接口标准与一个被代理类(真正干活的)代理类可以在运行时创建全新的类,这样的代理类可以实现指定的接口。

天宇龙腾的博客 579

探索robotics-toolbox-python:从基础安装到高级机器人运动学应用

本文详细介绍了robotics-toolbox-python工具箱,从基础安装、环境配置到机器人运动学与动力学的核心应用。通过D-H参数、URDF导入和内置模型三种方式快速构建机器人模型,并演示了正逆运动学计算、关节空间与任务空间轨迹规划以及三维可视化仿真。该工具箱极大地简化了机器人算法开发流程,是进行机器人学研究和应用实践的强大工具。

i1j2k的博客 496

c++代理类

上述的策略在不需要修改实际对象时非常有用,即所有代理类对象只是读它所代理的实际对象时,但当某个代理类需要修改它所代理的实际对象时,问题就发生了,由于所有代理类对象实际所代理的对象在内存中是同一份,因此,一个代理类对象所做的修改将会影响其他代理类,因此,此时需要对所代理的实际对象进行复制,且该复制是无法避免的。但上述方法实施的前提是我们明确的知道了要放入parking_lot中的对象的静态类型,在本例中,我们知道要放入parking_lot的是RoadVehicle,而不是AirCraft或其他的类对象。

quaer的博客 1250

香橙派5使用RK3588S内置NPU加速yolov5推理,实时识别数字达到50fps

香橙派5采用了RK3588S,内置的NPU达到了6Tops的算力,博主这里记录一下自己的踩坑过程,好不容易做出来的不能以后忘记了(手动狗头)。这里博主还在B站上发布了效果视频,大家感兴趣的话可以看一下。其中解决了先验框标注位置不对,或者出现非常多的框的问题

weixin_51651698的博客 2万+

esim分布式云卡池技术

eSIM卡,即Embedded-SIM,嵌入式SIM卡。eSIM卡的概念就是将传统SIM卡直接嵌入到设备芯片上,而不是作为独立的可移除零部件加入设备中,用户无需插入物理SIM卡。这一做法将允许用户更加灵活的选择运营商套餐,或者在无需解锁设备、购买新设备的前提下随时更换运营商。未来通用的eSIM标准建立将为普通消费者、企业用户节省更多移动设备使用成本,并带来更多的便利、安全性。 2018年 3月7日,中国联通宣布,正式在上海、天津、广州、深圳、郑州、长沙6座城市率先启动“eSIM一号双终端”业务的办理。[.

著名博客 3708

cglib动态代理 | 如何生成代理类、代理类内容解析

CgLib(Code Generation Library)是一个针对java,且开源的代码生成类库,封装了ASM,ASM可以直接产生二进制class文件。

devops 5153

matlab 一维相位解缠

一维相位解缠算法的matlab代码实现。

点云侠的博客 373

代理类——java理解

代理模式:代购,代练 特点:一个接口,两个子类,其中一个子类负责完成真实业务,另一个子类辅助之 代理类中: 1.需要传入真实业务对象,代理类需要知道真实客户是谁,完成真实业务是由真实对象来完成,代理制需要辅助之(掏钱是客户,并不是代购)通过构造方法传入(下订单时,商家已经知道客户是谁) 2.传入的是接口对象,只要是接口中定义的业务,代理类都可以进行代理,(只要是买电脑,代购都可以处理,入传...

qq_41832361的博客 1702

RK3568移植AP6256

本文主要是记录RK3568移植正基的AP6256的WIFIBT模块,感兴趣的朋友可以一起学习!!!提示:以下是本篇文章正文内容,下面案例可供参考。

qq_24093081的博客 3715

华为OD机试真题 新系统2026-04-15 Python&JS 实现【失灵的键盘】

有一个键盘有2个按键失灵了,按下这些键时会连续输出其他键对应的字符两次。具体如下: 1. 按下j键一次,屏幕上显示uu(两个连续的u);  按下b键一次,屏幕上显示t(两个连续的t) 2. u键和t键是好的,按下u键一次时,屏幕只会显示一次u(正常按键);按下t键一次时,屏幕只会显示一次t(正常按键) 3. 假定屏幕上连续显示两个t一定是按了一次b键,而不是两次t键;假定按键t之后不会紧接着按键b,即tttt转义为两个b,而不可能是tb

MISAYAONE的博客 523

WebRTC代理类

我们以 PeerConnectionFactory 为例说明如何定义一个代理类。首先定义一个 PeerConnectionFactoryInterface 类,它继承自 rtc::RefCountInterface,然后在接口类中声明需要暴露的接口,例如 SetOptions,CreatePeerConnection,GetRtpSenderCapabilities 等接口都是需要对外暴露的接口。

椛茶的博客 1119

【AI智能体】Codex AI 辅助编程高级技能实战操作详解

Codex AI 辅助编程高级技能实战操作详解

congge 6760

代理类和AOP

代理类和AOP 客户端不用调用目标对象了,直接调用代理类。最终目标方法还是去实行了。 代理类的每个方法调用目标类的相同方法,并且在调用方法时候加上系统功能的代码 代理和目标实现了相同的接口,有相同的方法。通过接口进行引用 要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方法,非常麻烦。 JVM可以在运行期间动态生成类的字节码,这样...

art_code的博客 1218

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

spring代理类的属性为什么为null

通过分析前端请求后端private接口方法,发现改私有方法被直接调用,且该方法被调用的对象的属性为null,进而分析导致这样结果的原因和解决的方式

weixin_44790908的博客 1023

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Qt 自定义代理类

对qt 的代理进行了详细分析。

qq_71286244的博客 1923

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【qt】自定义代理类

自定义代理类主要应用于在视图中加入一些的组件,代理可以理解为是视图和模型的一个介质,可以让我们更好的实现我们想要的功能。

qq_74047911的博客 1351

基于代理类的AOP的实现

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录前言一、pandas是什么?二、保姆级别开发教程0.创建如下图目录:1.创建2.3.4.5.配置XML文件6.生成测试类7.实验结果+分析总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习

AI手套的博客 859
上一篇: tomcat基础
lukyaa
博客等级 码龄17年 1粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值