1. 用jvm动态生成类
package cn.itcast.day3;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
public class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) {
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println("----begin constructersList---");//声明开始打印构造函数
Constructor [] constructors=clazzProxy1.getConstructors();//用一个构造函数集合接收jvm产生的类的构造方法
for (Constructor constructor : constructors) {
String name=constructor.getName();//获得构造方法名
StringBuilder sBuilder=new StringBuilder(name);//建立一个StringBuilder对象
sBuilder.append('(');//在构造方法名后添加一个括号
Class[] clazzParams=constructor.getParameterTypes();//获得构造方法的参数列表
for (Class class1 : clazzParams) {
sBuilder.append(class1.getName()).append('.');//获得参数名并加,号
}
if (clazzParams!=null&&clazzParams.length!=0) {
sBuilder.deleteCharAt(sBuilder.length()-1);//如果有参数则去掉最后一个,号
}
sBuilder.append(')');//添加一个括号
System.out.println(sBuilder);//打印该构造方法
}
System.out.println("----begin method---");//打印该类的方法列表,同理
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 class1 : clazzParams) {
sBuilder.append(class1.getName()).append('.');
}
if (clazzParams!=null&&clazzParams.length!=0) {
sBuilder.deleteCharAt(sBuilder.length()-1);
}
sBuilder.append(')');
System.out.println(sBuilder);
}
}
}
2. 基本代理方法
代理方法的参数
参1:代理的是哪个对象 参2:参数中的哪个方法 参3:参数要传进来的参数
Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler()
{
ArrayList arrayList=new ArrayList();//要代理方法的对象
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
long beginTime=System.currentTimeMillis();//方法开始时间
Object retVal=arg1.invoke(arrayList, arg2);//执行要代理的方法
long endTime=System.currentTimeMillis();//方法结束时间
System.out.println(endTime-beginTime);//方法运行用时
return retVal;//返回要代理方法的返回值
}
}
);
proxy3.add(1);//调用代理后的方法
proxy3.add(2);
proxy3.add(4);
System.out.println(proxy3.size());//打印集合长度
3. 自定义一个代理的框架
1) 定义Advice接口
package cn.itcast.day3;
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod(Method method);//目标方法前调用的方法
void afterMethod(Method method);//目标方法后调用的方法
}
2) 实例化Advice接口
package cn.itcast.day3;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
long beginTime;
long endTime;
public void afterMethod(Method method) {
endTime=System.currentTimeMillis();
System.out.println(endTime-beginTime);
}
public void beforeMethod(Method method) {
beginTime=System.currentTimeMillis();
}
}
3) 制作代理框架
private static Object getProxy(final Object target/*需要代理的对象*/,final Advice advice/*该对象要添加的功能接口*/) {
Object proxy3=Proxy.newProxyInstance(Object.class.getClassLoader()/*获得类加载器*/,
target.getClass().getInterfaces()/*获得目标类的接口*/,
new InvocationHandler()
{
public Object invoke(Object arg0, Method method, Object[] para)
throws Throwable {
advice.beforeMethod(method);//方法调用前操作
Object retVal=method.invoke(target, para);//执行要代理的方法
advice.afterMethod(method);//方法调用后的操作
return retVal;//返回要代理方法的返回值
}
}
);
return proxy3;
}
4..实现类似Spring的可配置AOP框架
1)配置文件
#xxx=java.util.ArrayList
xxx=cn.itcast.day3.aopframework.ProxyFactoryBean
xxx.advice=cn.itcast.day3.MyAdvice
xxx.target=java.util.ArrayList
2)委托的添加方法代码
package cn.itcast.day3;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
long beginTime;
long endTime;
public void afterMethod(Method method) {
endTime=System.currentTimeMillis();
System.out.println(endTime-beginTime);
}
public void beforeMethod(Method method) {
beginTime=System.currentTimeMillis();
}
}
3) 委托工厂
package cn.itcast.day3.aopframework;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.itcast.day3.Advice;
public class ProxyFactoryBean {
private Object target;//设置需要委托的类为该方法的属性
private Advice advice;//设置aop
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getProxy() {
Object proxy3=Proxy.newProxyInstance(Object.class.getClassLoader()/*获得类加载器*/,
target.getClass().getInterfaces()/*获得目标类的接口*/,
new InvocationHandler()
{
public Object invoke(Object arg0, Method method, Object[] para)
throws Throwable {
advice.beforeMethod(method);//方法调用前操作
Object retVal=method.invoke(target, para);//执行要代理的方法
advice.afterMethod(method);//方法调用后的操作
return retVal;//返回要代理方法的返回值
}
}
);
return proxy3;
}
}
4) bean工厂
package cn.itcast.day3.aopframework;
import java.io.*;
import java.util.Properties;
import cn.itcast.day3.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) throws Exception//通过类名返回Bean
{
String className=props.getProperty(name);//获得要加载的名称
Class clazz=Class.forName(className);//获得加载的类
Object bean=clazz.newInstance();//实例化类
if (bean instanceof ProxyFactoryBean) {//如果该类是委托工厂型的,则进入
ProxyFactoryBean proxyFactoryBean=(ProxyFactoryBean)bean;//获得这个工厂
Advice advice=(Advice)Class.forName(props.getProperty(name+".advice")).newInstance();//获得Advice子类的对象
Object target=Class.forName(props.getProperty(name+".target")).newInstance();//获得要委托的类
proxyFactoryBean.setAdvice(advice);//给工厂属性赋值
proxyFactoryBean.setTarget(target);
Object proxy=((ProxyFactoryBean)bean).getProxy();//获得target的委托类
return proxy;
}
return bean;//返回原来的类
}
}
5) 测试类
package cn.itcast.day3.aopframework;
import java.io.InputStream;
import java.util.Collection;
public class AopFrameworkTest {
public static void main(String[] args)throws Exception {
InputStream ips=AopFrameworkTest.class.getResourceAsStream("config.properties");//获得文件流
Object bean=new BeanFactory(ips).getBean("xxx");//通过bean工厂获得bean
System.out.println(bean.getClass().getName());//获得类型名 原类/委托类
((Collection)bean).clear();//调用方法
}
}