加强2注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。

 

/*
注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。
*/


/*了解注解及java提供的几个基本注解,比枚举还要重要。
	java.lang包下面有三个基本注解。
	注解相当于一个标记,加了注解等于为程序打上某种标记,加了注解后编译器会通过反射来
	了解你这个元素上有没有加标记。看你有什么标记,就去干什么事。标记加在包,类,字段,
	方法,方法的参数以及局部变量上等等。
*/
public class AnnotationDemo {
	/**一个注解就是一个类。三个基本注解
	 * @param args
	 */
	@SuppressWarnings( "deprecation" )//这样加表示不提示过时,这就是一个注解
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.runFinalizersOnExit(true);//字体上划线表示过时了。
	}

	@Deprecated//这样加上是说这个方法过时了。
	public static void sayHello(){
		System.out.println("hi,itcast");
	}//这个方法用很久之后,有更好的其他方法,在这就说已经过时。

	@Override//这样加可以提示复写是否错误
	public boolean equals(AnnotationDemo an){//复写父类的equals,参数要为Object
		return true;//要修改参数类型为Object
	}
}

/*
注解的应用
	定义注解类:
	@interface A{}

	应用了"注解类"的类
	@A
	class B{}

	对应用了注解的类,进行反射操作的类
	class C{
		B.class.isAnnotPresent(A.class);
		A a = B.class.getAnnotion(A.class);
	}
*/

图片。。。注解的应用。。。。。

《加强2注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。》










/*
元注解。
@Retention(RetentionPolicy.RUNTIME),注解上面加上这个注解,保持到运行时期.
因为加载进内存时,没注明就会去掉注解。
注解的三个阶段:源文件(SOURCE)-->class文件(CLASS)——>内存阶段(RUNTIME)。

@Target()//可以定义在谁身上,如方法。
*/
@Retention(RetentionPolicy.RUNTIME)//注解可以保留到编译时期。
@Target(@Target(ElementType.TYPE))//这个注解只能应用到TYPE上。
@interface A{}//定义一个注解

@A
class B{}//应用了注解的类

class C{//通过反射操作运用了注解的类上的注解A
	public static void main(String[] args){
		if(B.class.isAnnotationPresent(A.class)){//判断B上是否加了注解A
			A a = B.class.getAnnotation(A.class);//得到A注解
			System.out.println(a);//@cn.itcast.day2.A().
		}
	}
}
/*
为注解增加基本属性

数组类型的注解:后面给值时,当数组值只有一个,{}可省略
枚举类型的注解:
注解类型的注解:
*/

@Retention(RetentionPolicy.RUNTIME)//注解可以保留到编译时期。
@Target(ElementType.TYPE)//可以定义在哪些目标上。
@interface A{//定义一个注解
	String color();//注解添加属性
	String value()default "haha";//有默认值,下面没设置就是它
	int[] arr();
	//EnumTest.TrafficLamp lamp();枚举属性注解
	//注解名 annotationAttr();
}
	
@A(color="red", arr={1,2})
class B{}//应用了注解的类

class C{//通过反射操作运用了注解的类上的注解A
	public static void main(String[] args){
		if(B.class.isAnnotationPresent(A.class)){//判断B上是否加了注解A
			A a = B.class.getAnnotation(A.class);//得到A注解
			System.out.println(a.value());//得到注解的值。
			System.out.println(a.color());
		}
	}
}

/*
泛型:提供给Javac编译器使用的,可以限定集合中的输入类型。
让编译器挡住源码的非法输入。但编译后泛型会被去掉。
为什么编译后要被去掉?如果不去掉,就要修改底层的东西,很麻烦。
泛型是给编译器看的,那么我通过反射就可以向限定<Integer>的集合,添加String类。

*/
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		ArrayList<Integer> al = new ArrayList<Integer>();
		
		//al.add("abc");
		al.add(12);
		al.getClass().getMethod("add", Object.class).invoke(al, "abc");
		//反射加入了("abc");
		System.out.println(al.get(1));
	}

/*

创建数组实例时,数组的元素不能使用参数化的类型。

泛型不考虑继承关系。
Vector<Object> v =  new Vector<String>;这样就是错误的了。
但如下这样写。
Vector v1 = new Vector<String>;
Vector<Object> v = v1;
这二行代码不会报错,因为编译器是一行一行的看的。


*/

/*
	引出通配符?,打印任意参数化类型集合的内容。

	参数类型是Collection<Object>,实际传入了ArrayList<String>,这样就不行。
	参数类型是Collection<?>,使用通配符才行。

	通配符的扩展(限定符总是包括自己。)
	上限:<? extends Integer>
	下限:<? supper Integer>
*/

//使用Map集合的迭代,Map.Entry<k,v>.自己写代码应用。



	//泛型方法
	private static<T>T add(T x,T y){//泛型定义
		return null;
	}//T要定义在返回值之前,记住这点。
	Number x1 = add(3.5,3);
	Object x2 = add(3,"abc");//类型的推断。

	//泛型不能定义成基本类型,T[] 指向 int[],这是不行的。
	//Number x1 = add(3.5,3);//这个可以是因为自动装箱。

	private static <T> T autoConvert(Object obj){//将任意类型转换成返回类型。
		return (T)obj;
	}

	//泛型类
	public class GenericDao<E>//
	{
		public void save(E obj){}
		public E findById(int id){return null;}
		public void delete(E obj){}
		public void delete(int id){}
		public void update(E obj){}
		public Set<E> findByConditions(String where){return null;}
	}//静态方法上不能用类上的泛型,因为静态先加载。

//利用反射实现这么一个功能,获取<>里面到底装的是什么类型。
	Vector<Data> v = new Vector<Data>();

	//从对象上没法获得,从方法上可以得到。

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Vector;

public class GetArgsGeneric {
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		Vector<Date> v = new Vector<Date>();
		Method method = GetArgsGeneric.class.getMethod("getArgs", Vector.class);//得到这个方法
		Type[] types = method.getGenericParameterTypes();//得到参数化的类型参数,数组。jdk1.5
		ParameterizedType pType = (ParameterizedType)types[0];//只接收一个参数
		System.out.println(pType.getRawType());//得到原始的类型
		System.out.println(pType.getActualTypeArguments()[0]);//得到实际化的类型参数
	}
	public static void getArgs(Vector<Date> v){
		//从v是不可以得到的,通过getArgs()方法可得到。
	}
}
/*
类加载器及其委托机制的深入分析:
	系统默认的三个主要类加载器:BootStrap,ExtClassLoader,AppClassLoader
	
	类加载器也是Java类,因为其他是java类的类加载器本身也要被加载。
	显然必须有第一个妈妈,BootStrap,它不是java类。是java虚拟机内核里的,
	C++语言写得一个代码。

	BootStrap(爷爷)-->ExtClassLoader(父)-->AppClassLoader(孙子)
	1.BootStrap:			JRE/lib/rt.jar
	2.ExtClassLoader:		JRE/lib/ext/*.jar
	3.AppClassLoader:		ClassPath指定的所有jar或目录。
	4.自定义的类加载器ClassLoader(父类参数),构造方法。

	都有文件的话,就要考虑优先级的问题,这就是委托机制。
	加载器加载类时,先交给父类加载器。爷爷找到了,下面的就不再找了。
	爷爷加载器没找到就交给父类,父类还没找到,自己找,还没找到就报错。

	线程运行时。可以指定类加载器。
	还可以直接调用ClassLoader.loadClass(),

*/


//自己编写一个类加载器。编写一个对文件内容进行简单加密的程序
	/*原理:
	1.必须继承一个抽象类ClassLoader
		2.覆盖父类的findClass()//得到class文件,再用defineClass()方法,把二进制数组变成.class返回。.

编写和测试自己编写的解密类加载器

*/
import java.util.Date;
//这个类用作需要加密的类
public class MyLoader extends Date {

	@Override
	public String toString(){
		return "Hello,java";
	}
}

public class MyLoaderTest {

	/**用作运行加密类
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(	new MyLoader());
	}
}

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader extends ClassLoader {

	/**我的类加载器,从参数输入
	 * @param args
	 * @throws Exception 
	 */
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		String srcPath = args[0];//要加密加载的源文件。
		String postDir = args[1];//加密后封存的文件夹
		InputStream is = new FileInputStream(srcPath);
		
		String postFileName = srcPath.substring(srcPath.lastIndexOf("\\")+1);
		String postPath = postDir+"\\"+postFileName;
		OutputStream os = new FileOutputStream(postPath);
		cyFile(is,os);//加密文件。
		
	}
	//加密文件。
	public static void cyFile(InputStream in,OutputStream out) throws IOException{
		int len = 0;
		while((len=in.read())!=-1){
			out.write(len ^ 0xff);//异或加密,解密。
		}
		in.close();
		out.close();
	}
	
	String name;//这些暂时不用。
	public MyClassLoader(){}
	public MyClassLoader(String name){
		this.name = name;
	}
}
//我们看到,当用加密后的文件覆盖掉原文件.class后,打印不出来结果。
//这是因为appclassLoader不能加载我们加密的class文件。



//这里写自己的类加载器的代码
import java.util.Date;
//这个类用作需要加密的类
public class MyLoader extends Date {//继承为了后面的创建对象

	@Override
	public String toString(){
		return "Hello,java";
	} 
}

/**用作运行加密类
	 * @param args
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//System.out.println(new MyLoader());//打印app加载的原来的class
		
		//用我自己的类加载器加载。
		Class clazz = new MyClassLoader("itcastlib").loadClass("MyLoader");//父类要加载,要加包名。
		Date d1 = (Date)clazz.newInstance();//(MyLoader)这样写不行的,因为MyLoader类程序要先去加载。只能用父类。
		System.out.println(d1+"111");//一开始运行出错,因为父类已经找到了,我们要先去删除相应的class
								//老师的视频要重启eclipse才行解决,因为。jar已经加载进内存了
								
								 // E:\eclipse4\javaenhance2\itcastlib\MyLoader.class
	}
}

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader extends ClassLoader {

	/**我们的类加载器
	 * @param args
	 * @throws Exception 
	 */
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		String srcPath = args[0];//输入需要加密的class文件绝对路径
		InputStream is = new FileInputStream(srcPath);
		
		String postDir = args[1];//输入要输出到哪个文件夹
		String postFileName = srcPath.substring(srcPath.lastIndexOf("\\")+1);//文件名一样
		String postPath = postDir+"\\"+postFileName;
		OutputStream os = new FileOutputStream(postPath);
		cyFile(is,os);//运行这里就是自己加密文件
		
	}

	@Override//这里是关键,extends ClassLoader复写findClass()方法。
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		// TODO Auto-generated method stub//name是我们要加载的文件名。路径会通过构造方法传递过来
		String classfileName = classDir + "\\" +name+".class";//通过下面构造函数得到路径
		try {
			InputStream is = new FileInputStream(classfileName);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			cyFile(is,bos);//解密到字节数组流中
			System.out.println("myclassloader");
			is.close();
			byte[] bytes = bos.toByteArray();//转换成字节数组
			bos.close();
			return defineClass(bytes, 0, bytes.length);//这个方法把字节数组转成.class文件返回
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return super.findClass(name);
	}
	//加密文件。
	public static void cyFile(InputStream in,OutputStream out) throws IOException{
		int len = 0;
		while((len=in.read())!=-1){
			out.write(len ^ 0xff);//异或加密,解密。
		}
		in.close();
		out.close();
	}
	
	String classDir;
	public MyClassLoader(){}
	public MyClassLoader(String classDir){
		this.classDir = classDir;
	}
}


//这里写测试程序的主函数。
	//通过构造方法和方法的参数传路径和文件名过去。
	Class clazz = new MyClassLoader("E:\\eclipse4\\javaenhance2\\itcastlib").loadClass("MyLoader");
	Date d = (Date) clazz.newInstance();
	System.out.println(d+"...");

	//Class clazz = new MyLoader().getClass();
	ClassLoader myLoader = clazz.getClassLoader();
	System.out.println(myLoader);//得到自己的类加载器。
	
	while(myLoader!=null){//打印上级父类加载器
		System.out.println(":"+myLoader);
		myLoader = myLoader.getParent();
	}
	/*把自己的类加载器加载出来的文件。jar到ext加载器的文件夹下,也不能加载。
	 * */

/*
我们看到编写自己的类加载器,先要把本来编译好的.class文件加密到我们的文件夹下。
这个文件是父类加载器加载不了的.class文件。

自己的类加载器要继承ClassLoader,复写其中的findClass()方法,findClass方法里面有
调用一个方法defineClass(byte[],0 len),可以把字节数组转换成Class文件返回。

当我们调用自己的类加载器时,调用的是loadClass()方法。而不是findClass()方法。

*/

	

/*
代理的概念与作用原理,AOP概念。
	生活中买电脑,在本地代理买,去北京联想总部买。。
	程序中的代理
	要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,
	例如:异常处理、日志、计算方法的运行时间、事务管理等等,准备如何做?

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


	AOP概念。面向方面的编程。
	AOP的目标就是要使交叉业务模块化。可以采用将切面代码转移到原始代码周围,
	这样的效果看起来和放在原始代码里是一样的。
	代理技术正好可以解决这种问题,代理是实现AOP的核心关键技术。

	要为系统中的各种接口的类增加代理,将需要太多的代理类,全部采用静态生成,
	成百上千,是不是很累?
	JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,
	就是动态代理类。
	JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作
	具有相同接口的目标类的代理。
	CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,
	所以,如果要为一个没有实现接口的类生成动态类,那么可以使用CGLIB库。

	代理类中的各个方法通常除了要调用目标的相应方法和对外返回结果外,
	还可以在如下位置加上系统功能代码:
	1在调用目标方法前
	2在调用目标方法后
	3在调用目标方法前后
	4在处理目标方法异常的catch块中

	方法:Proxy.getProxyClass(类加载器,接口),得到一个Class,造出一个类。
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;

public class ProxyDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Class clazzProxy = Proxy.getProxyClass(
				Collection.class.getClassLoader(), Collection.class);
		
		Constructor[] constructors = clazzProxy.getConstructors();
		System.out.println("-------ProxyConstructor List---------");
		//构造方法列表,并带上参数类型
		for(Constructor constructor: constructors){
			String nameCon = constructor.getName();
			StringBuilder sBuilder = new StringBuilder(nameCon);
			sBuilder.append("(");
			
			Class[] names = constructor.getParameterTypes();//参数类型
			//String	argsName = name.getTypeParameters();
			for(Class name:names){
				 
				sBuilder.append(name.getName()+",");
				}
			if(names!=null && names.length!=0){
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder.toString());
		}
		
		Method[] methods = clazzProxy.getMethods();
		System.out.println("-------ProxyCMethods List---------");
		//成员方法列表,并带上参数类型
		for(Method method:methods){
			String nameMethod = method.getName();
			StringBuilder sBuilder = new StringBuilder(nameMethod);
			sBuilder.append("(");
			Class[] classMethods = method.getParameterTypes();
			for(Class classMethod :classMethods){
				sBuilder.append(classMethod.getName()+",");
			}
			if(classMethods!=null && classMethods.length!=0)
				sBuilder.deleteCharAt(sBuilder.length()-1);
			sBuilder.append(")");
			System.out.println(sBuilder.toString());
		}

		/*
		创建动态类的实例对象
		*/
		System.out.println("----------------------------");
		Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);
		
		class MyInvocationHandler1 implements InvocationHandler{

			public Object invoke(Object arg0, Method arg1, Object[] arg2)
					throws Throwable {
				// TODO Auto-generated method stub//抽象方法必须要复写。
				return null;
			}
		}
		
		Collection proxy1 = (Collection) constructor.newInstance(
				new MyInvocationHandler1());
		System.out.println(proxy1);
		//invo1.clear();


		//2.匿名内部类改写。通过构造函数创建实例对象。
		Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){

			public Object invoke(Object arg0, Method arg1, Object[] arg2)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
		});
		System.out.println(proxy2);
		
		//3.创建类Class和实例对象。一步到位Proxy.newProxyInstance();
		Collection proxy3 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),
				new Class[]{Collection.class},
				new InvocationHandler(){

			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				ArrayList target = new ArrayList();//定义目标

				long beginTime = System.currentTimeMillis();

				
				Object  retVal = method.invoke(target,args);//这里是怎么定义目标的

				long endTime = System.currentTimeMillis();
				
				return retVal;
			}
		});
		System.out.println(proxy3);//如果上面为空,这里会错。空指针
	}
}


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 ProxyDemo2 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Collection coll3 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				new Class[]{Collection.class}, 
				new InvocationHandler() {			
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						ArrayList target = new ArrayList();//目标

						long startTime = System.currentTimeMillis();

						Object retVal = method.invoke(target, args);

						Thread.sleep(3000);
						long endTime = System.currentTimeMillis();
						System.out.println(method.getName()+":time:"+(endTime-startTime));
						return retVal;
						//return method.invoke(proxy, args);这样写会死循环。
					}
				});
		
		//System.out.println(coll3);
		coll3.add("1...");//每调用一次add方法,都会去执行invoke().
		coll3.add("2...");
		coll3.add("3...");
		System.out.println(coll3.size());
	}
}
/*每一个代理实例对象调用方法时,都会把对象,方法,参数传给invoke()方法,到里面去执行。invoke()返回结果
就是代理调用方法的返回结果。而我们通常会把目标target传进去Object retVal = method.invoke(target, args);
这样目标方法的返回结果就是代理方法的返回结果了。

实际上还可以在传入参数之前,把参数结果修改。
Object retVal = method.invoke(target, args);
还可以在最后把返回结果进行修改return retVal;。

这样我们就可以解释上面调用代理对象的size()方法时为什么会出错了。
coll3.size(),我们要的是一个整数,而你返回的是null,要我把null转成整数,肯定会错。

那么为什么这个结果正确呢?按照刚才的理论不是交给invoke去执行吗?
System.out.println(coll3.getClass().getName());//$Proxy0
通过查询API,知道Object中只有hashCode(),equals(),toString()三个方法交给
handler去实现。Object类其他方法有自己的实现。

*/
/*
、要把代码传进去去Handler的invoke()方法,这是不现实的,但我们可以把代码封装成一个对象的方法,
我们把对象传进去,这是可以的,那我们再调用对象的这个方法,代码不是可以运行了吗?就是这样。
这就是面向切面编程。

那怎样把目标类传进去?
1,直接在invocationHandler实现类中创建,没实际意义。
2.为invocationHandler实现类注入目标类的实例对象,不能采用匿名内部类的形式了。
3.让匿名的invocationHandler实现类访问外面方法中的目标类实例对象的final类型的引用变量。

要为invocationHandler传递目标类,还要传递系统功能的对象。
*/

import java.lang.reflect.Method;
public interface Advice {
	//创建用于传递进去的功能对象,要实现的接口
	void beginTime(Method method);
	void afterTime(Method method);
}

import java.lang.reflect.Method;
public class MyAdvice implements Advice {
	//实际传递进去的对象,实现系统功能。
		long beginTime ;
	public void beginTime(Method method) {
		// TODO Auto-generated method stub
		System.out.println("itcast begin...");
		beginTime = System.currentTimeMillis();
	}

	public void afterTime(Method method) {
		// TODO Auto-generated method stub
		System.out.println("itcast after...");
		long afterTime = System.currentTimeMillis();
		System.out.println(method+",runTime:"+(afterTime-beginTime));
		System.out.println("itcast end...");
	}
}

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 ProxyDemo {
	public static void main(String[] args) {
	
		final Object target = new ArrayList();//创建final目标类。
		Collection coll = (Collection)getProxy(target,new MyAdvice());
		coll.add("32131313");
		coll.size();
	
	}
	//拿到目标对象,系统功能的对象,就返回一个代理类对象。方法抽取。
	private static Object getProxy(final Object target, final Advice advice) {
		Object obj = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler() {
					
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						//long beginTime = System.currentTimeMillis();
						advice.beginTime(method);
						Object retVal = method.invoke(target, args);
						advice.afterTime(method);
						//long afterTime = System.currentTimeMillis();
						//System.out.println(method+",runTime:"+(afterTime-beginTime));
						return retVal;
					}
				});
		return obj;
	}
}

/*
	实现AOP功能的封装与配置。类似Spring
	工厂类BeanFactory.负责创建目标类或代理类的实例对象。并通过配置文件进行切换。
	Object obj = BeanFactory("xxx");
*/


import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import ProxyDemo.Advice;

public class BeanFactory {
	Properties props = new Properties();
	public BeanFactory(InputStream ips){
		try {
			props.load(ips);//载入输入流。
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public Object getBean(String name){
		String className = props.getProperty(name);
		Object bean = null;
		
		try {
			Class clazz = Class.forName(className);
			 bean = clazz.newInstance();//创建对象
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(bean instanceof ProxyFactoryBean){//判断是否是ProxyFactoryBean类
			//是的话,就返回它的代理类对象。
			Object proxy = null;
			ProxyFactoryBean proxyFactoryBean = ((ProxyFactoryBean)bean);
			
			try {
				Advice advice = (Advice) Class.forName(props.getProperty(name+".advice")).newInstance();
				Object target = Class.forName(props.getProperty(name+".target")).newInstance();
				
				proxyFactoryBean.setAdvice(advice);//设置系统功能接口的代码对象xxx.advice=ProxyDemo.MyAdvice

				proxyFactoryBean.setTarget(target);//设置目标。xxx.target=java.util.ArrayList
				 proxy = proxyFactoryBean.getProxy();//调用得到代理类的方法。
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
			
			return proxy;//返回代理类
		}
		return bean;//不是就直接返回bean对象。
	}

}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import ProxyDemo.Advice;
//是的话就调用这个类的getProxy()
public class ProxyFactoryBean {
	
	private Advice advice;
	public Advice getAdvice() {
		return advice;
	}

	public void setAdvice(Advice advice) {
		this.advice = advice;
	}

	public Object getTarget() {
		return target;
	}

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

	private Object target;
	
	public Object getProxy(){
		Object obj = Proxy.newProxyInstance(
			target.getClass().getClassLoader(),//三个方法参数
			target.getClass().getInterfaces(),
			new InvocationHandler() {//匿名内部类
				
				public Object invoke(Object proxy, Method method, Object[] args)
						throws Throwable {
					//long beginTime = System.currentTimeMillis();
					advice.beginTime(method);
					Object retVal = method.invoke(target, args);
					advice.afterTime(method);
					//long afterTime = System.currentTimeMillis();//用上面的功能代码实现
					//System.out.println(method+",runTime:"+(afterTime-beginTime));
					return retVal;
				}
			});
		return obj;
	}
}

import java.io.InputStream;
public class AopFrameworkTest {

	/**测试程序
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
		Object bean = new BeanFactory(ips).getBean("xxx");
		System.out.println(bean.getClass().getName());
	}

}

//config.properties文件中的内容

#xxx=java.util.ArrayList
xxx=cn.itcast.day2.aopframework.ProxyFactoryBean
xxx.advice=ProxyDemo.MyAdvice
xxx.target=java.util.ArrayList


import java.lang.reflect.Method;
//需要传递进去的功能代码,用于创建对象
public class MyAdvice implements Advice {
	//实际传递进去的对象,实现系统功能。
		long beginTime ;
	public void beginTime(Method method) {
		// TODO Auto-generated method stub
		System.out.println("itcast begin...");
		beginTime = System.currentTimeMillis();
	}

	public void afterTime(Method method) {
		// TODO Auto-generated method stub
		System.out.println("itcast after...");
		long afterTime = System.currentTimeMillis();
		System.out.println(method+",runTime:"+(afterTime-beginTime));
		System.out.println("itcast end...");
	}
}

《加强2注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。》

《加强2注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。》

《加强2注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。》

《加强2注解。泛型。类加载器及其委托机制。代理的概念与作用原理,AOP概念。实现AOP功能的封装与配置。类似Spring。》

    原文作者:AOP
    原文地址: https://blog.csdn.net/luck28/article/details/8558117
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞