-------------java培训、android培训、java博客、java学习型技术博客、期待与您交流! --------------
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中
package cn.itcast.day3;
import java.lang.reflect.Method;
public interface Advice {
/* 1.在调用目标方法之前
* 2.在调用目标方法之后
* 3.在调用目标方法前后
* 4.在处理目标方法异常的catch块中*/
void beforeMethod(Method method);
void afterMethod(Method method);
}
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 {
public static void main(String[] args) throws Exception {
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){
String name = constructor.getName();
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);
}
System.out.println("----------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);
}
System.out.println("----------begin create instance object ----------");
Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
//InvocationHandler是个接口,自己做过实现类,然后传入。
class MyInvocationHandler1 implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
}
//InvocationHandler是个接口,自己做过实现类,然后传入。
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHandler1());
//用匿名内部类方法创建对象
Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
//说明对象已经创建成功,但是返回值是null
System.out.println(proxy1.toString());
/*但是有返回值的方法无法调用
* 原因是:上面的InvocationHandler子类的invoke()方法返回值是null */
//proxy1.size();
/*返回值为void的方法可以调用
*原因是:上面的InvocationHandler子类的invoke()方法返回值是null*/
proxy1.clear();
//抽取出来的target,内部类要直接访问外部类中的成员变量,必须被final修饰
final ArrayList target = new ArrayList();
Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
//程序调用proxy3.add("zxx");方法时,涉及三要素:proxy3对象、add方法、"zxx"参数
proxy3.add("zxx");
proxy3.add("lhm");
Object proxy3retValue = proxy3.add("bxd");
System.out.println("--------------proxy3.add(bxd);"+proxy3retValue);
System.out.println(proxy3.size());
System.out.println(proxy3.getClass().getName());
}
//修改成通用的,就要把返回值Collection改成Object
private static Object getProxy(final Object target,final Advice advice) {
//用Proxy.newInstance方法直接一步就创建出代理对象。
Object proxy3 = Proxy.newProxyInstance(
/*Collection proxy3 = (Collection)Proxy.newProxyInstance(*/
target.getClass().getClassLoader(),
/*Collection.class.getClassLoader(),*/
target.getClass().getInterfaces(),
/*new Class[]{Collection.class},*/
//在InvocationHandler内部指定动态类的目标
new InvocationHandler(){
/*如果ArrayList target = new ArrayList();放在这里,
* ArrayList就是InvocationHandler子类的成员变量
* 结果就是 3。
* */
//将ArrayList target = new ArrayList();抽取到外部类中,即内部类访问外部类
//ArrayList target = new ArrayList();
// ( proxy3对象 , add方法, "zxx"参数)
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*如果ArrayList target = new ArrayList();放在这里,
* proxy3.add("zxx");
* proxy3.add("lhm");
* proxy3.add("bxd");
* proxy3每次调用add()都会找InvocationHandler子类中的invoke()方法,
* 但是此时,每次都会新建一个new ArrayList();。
* proxy3.size()被调用也是新的ArrayList。
* 所以结果会是 0.
*/
//ArrayList target = new ArrayList();
/*long beginTime = System.currentTimeMillis();
Object retValue = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out
.println(method.getName() + "running time of "
+ (endTime - beginTime));*/
advice.beforeMethod(method);
Object retValue = method.invoke(target, args);
advice.afterMethod(method);
//打印true,表示proxy3.add("zxx");添加元素操作成功!!
//System.out.println(retValue);
return retValue;
//如果这样写,就是在此调用,递归,死循环
//return method.invoke(proxy, args);
}
});
return proxy3;
}
}
运行结果
$Proxy0
----------begin constructors list----------
$Proxy0(java.lang.reflect.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()
----------begin create instance object ----------
null
到传智播客学习啦!
addrunning time of 0
从传智播客毕业上班了!
到传智播客学习啦!
addrunning time of 0
从传智播客毕业上班了!
到传智播客学习啦!
addrunning time of 0
从传智播客毕业上班了!
--------------proxy3.add(bxd);true
到传智播客学习啦!
sizerunning time of 0
从传智播客毕业上班了!
3
$Proxy1
package cn.itcast.day3;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
long beginTime=0;
@Override
public void beforeMethod(Method method) {
System.out.println("到传智播客学习啦!");
beginTime = System.currentTimeMillis();
}
@Override
public void afterMethod(Method method) {
long endTime = System.currentTimeMillis();
System.out
.println(method.getName() + "running time of "
+ (endTime - beginTime));
System.out.println("从传智播客毕业上班了!");
}
}
实现AOP功能的封装与配置
工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvice
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
目标
通知
编写客户端应用:
编写实现Advice接口的类和在配置文件中进行配置
调用BeanFactory获取对象
package cn.itcast.day3.aopframwork;
import java.io.InputStream;
import java.util.Collection;
public class AopFramworkTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//因为配置文件使用的是相对路径,所以配置文件要和AopFramworkTest在同一个目录下
InputStream ips = AopFramworkTest.class.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
((Collection)bean).clear();
}
}
运行结果
$Proxy0
到传智播客学习啦!
clearrunning time of 0
从传智播客毕业上班了!
package cn.itcast.day3.aopframwork;
import java.io.IOException;
import java.io.InputStream;
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){
String className = props.getProperty(name);
Object bean = null;
try {
Class clazz = Class.forName(className);
//对已JavaBean类一定要有无参构造方法
//原因:是clazz.newInstance();只有newInstance()的方法
bean = clazz.newInstance();
} catch (Exception e) {e.printStackTrace();}
if(bean instanceof 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);
proxyFactoryBean.setTarget(target);
proxy = proxyFactoryBean.getProxy();
} catch (Exception e) {e.printStackTrace();}
return proxy;
}
return bean;
}
}
package cn.itcast.day3.aopframwork;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.itcast.day3.Advice;
public class ProxyFactoryBean {
private Advice advice;
private Object target;
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getTarget() {
return target;
}
public void setTarget(Object targer) {
this.target = targer;
}
public Object getProxy() {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);
Object retValue = method.invoke(target, args);
advice.afterMethod(method);
return retValue;
}
});
return proxy3;
}
}
config.properties配置文件内容
#xxx=java.util.ArrayList
xxx=cn.itcast.day3.aopframwork.ProxyFactoryBean
xxx.advice=cn.itcast.day3.MyAdvice
xxx.target=java.util.ArrayList
-------------java培训、android培训、java博客、java学习型技术博客、期待与您交流! --------------