------- 物联云培训、java培训、期待与您交流! ----------
概念:实际上就是要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。
代理的作用:实际上就是在你的目标代码上,添加一些别的代码,你本身的代码也运行了。
这个新的代码就是代理。
代理类的好处:生成代理类后但你想要改变程序是不需要改变源程序。
交叉业务的编程问题即面向方面的编程(AOP),AOP的目标就是使交叉业务模块化,可以采用将切面代理移动到原始方法的周围,这与直接在方法中编写切面代理的过程效果是一样的。
实际上是面向一个面的,在一些目标方法的前后位置插入一些代码。
创建一个动态类:
Proxy:代理类
//得到一个类的class
Class clazz=
proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
这个代理类只有一个构造方法:
$proxy0(InvocationHandleri);
InvocationHandler是一个接口
//获取构造函数
Constructor constructor=clazz.getConstructor(InvocationHandler.class);
创建动态类的实例对象方式一
class MyInvocationHander1 implements InvocationHandler{
public Objectinvoke(Object proxy, Method method, Object[] args)
throwsThrowable {
// TODOAuto-generated method stub
return null;
}
}
创建动态类的实例对象方式二
Collection proxy2 = (Collection)constructor.newInstance(newInvocationHandler(){
public Objectinvoke(Object proxy, Method method, Object[] args)
throwsThrowable {
return null;
}
});
获得对象
Collection proxy1 =(Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);
proxy1.clear();
proxy1.size();
注意:不能调用有返回值的size方法,因为:size的返回int类型的,代码中是返回的null,null没有办法转变成int
//可以直接创建对象:
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
newInvocationHandler(){
publicObject invoke(Object proxy, Method method, Object[] args)
throwsThrowable{
}
目标类中的方法怎么在代理类中执行的呢?
实际上目标类中的方法每被调用一次,就会执行一次invote方法。
InvocationHander的运行原理是:
Invodler.invote(object proxy,Method method,Object[] args);
Objproxy.add(“fdsmfkdsl”);
proxy 接受Objproxy, method接受 add(), args 接受"fdsmfkdsl";
下面是一个代理类的代码:
//代理类
publicclassProxyTest {
publicstaticvoid main(String[] args) throws Exception {
ArrayList al=newArrayList();
Collectionconllection = (Collection)getProxy(al,newMyAdvice());
conllection.add("aaaa");
conllection.add("bbbb");
conllection.add("cccc");
conllection.add("dddd");
System.out.println(conllection);
}
privatestatic Object getProxy(final Objectobj,final Advice ad)
{
Collectionconllection=(Collection)Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
newInvocationHandler(){
ArrayListal=newArrayList();
public Objectinvoke(Object proxy, Method method, Object[] args)
throwsThrowable {
ad.beforeMethod(method);
Object val=method.invoke(al, args);
ad.afterMethod(method);
returnval;
}
});
returnconllection;
}
}
importjava.lang.reflect.Method;
publicclassMyAdviceimplementsAdvice {
longstart;
@Override
publicvoidafterMethod(Method method) {
// TODO Auto-generated method stub
longstart=System.currentTimeMillis();
}
@Override
publicvoidbeforeMethod(Method method) {
// TODO Auto-generated method stub
longend=System.currentTimeMillis();
System.out.println(method.getName()+"yunxing de shijan"+(end-start));
}
}
importjava.lang.reflect.Method;
publicinterface Advice {
voidbeforeMethod(Method method);
voidafterMethod(Method method);
}
利用动态代理模拟Spring框架
代码如下:
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.Properties;
importcn.itcast.day3.Advice;
publicclass BeanFactory {
Properties props = new Properties();
publicBeanFactory(InputStreamips){
try {
props.load(ips);
} catch (IOException e) {
// TODO Auto-generated catch block
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 instanceofProxyFactoryBean){
Object proxy = null;
ProxyFactoryBeanproxyFactoryBean =(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) {
// TODO Auto-generated catchblock
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy;
importcn.itcast.day3.Advice;
publicclass 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 target) {
this.target = target;
}
public Object getProxy() {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
newInvocationHandler(){
public Object invoke(Objectproxy, Method method, Object[] args)
throwsThrowable {
advice.beforeMethod(method);
Object retVal =method.invoke(target, args);
advice.afterMethod(method);
returnretVal;
}
}
);
return proxy3;
}
}
importjava.io.InputStream;
importjava.util.Collection;
publicclass AopFrameworkTest {
/**
* @paramargs
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
InputStreamips =AopFrameworkTest.class.getResourceAsStream("config.properties");
Object bean = newBeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
((Collection)bean).clear();
}
}
总结:代理:就是给目标类添加一个壳子,可以有效地添加系统功能和控制是否调用目标类。
静态代理:就是把代理的目标类已经人工的添加进去,当代码编译时,就会生成相应的class文件。
动态代理:就是有特定的方法,自动生成传入的目标类的代理类,在编译时,不会出现相应的class类。在程序运行时,运用反射机制动态创建而成
Proxy 已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。