何为代理?
1、为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能的类。(对真实类的增强)
2、一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
3、如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、
还是代理类,这样以后很容易切换。
4、轻易实现AOP(Aspect oriented program)功能。
动态代理开发步骤
1、明确要实现的接口
2、创建代理类
1)通过Proxy类的静态方法创建代理对象
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, Invocationhandler h)
参数ClassLoader loader:类的加载器,使用null表示使用默认的加载器。
真实对象的类加载器对象:真实对象的类名.class.getClassLoader();
参数 Class<?>[] interfaces:需要代理的接口数组。
即真实对象实现的接口的Class对象数组:
1.真实对象的类名.class.getInterfaces();
2.需要实现的泛型接口 可以用匿名对象new的方式传入.new Class[]{泛型接口名.class}
参数 Invocationhandler h:
调用处理器,使用新建的proxy对象调用方法的时候,都会调用到该接口中的invoke方法,传递一个回调处理
对象(InvocationHandler接口的实现类对象h)
注意:
处理器 是一个接口,不能直接new对象,
所以可以自定义一个类实现处理器接口再将实现类对象传入,
或者可以用匿名内部类的方式传入参数.
目标对象(需要增强的对象)都是维护在处理器内部的.
在定义方法产生代理对象时,要将增强的代理目标对象作为参数传入.
2)回调处理对象要重写一个invoke方法,在invoke方法里面进行指定方法的增强
该方法会拦截代理对象方法的调用,
在该方法中根据实际需求决定是否要调用真实对象的方法。
Invoke方法的参数说明
public object invoke (Object proxy , Method method , Object[]args);
proxy 代理对象
method 当前执行的方法
args 当前执行方法的实参
注意事项
在代理实例上的 java.lang.Object 中声明的 hashCode、equals 或 toString 方法将会调用代理类的invoke方法。
从Object类上继承的其他方法不会。
例子(实现Aop功能)
测试类
public class AopFrameworkTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// 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());
((Collection)bean).clear();
}
}
配置文件config.properties
#xxx=java.util.ArrayList
xxx=目录.ProxyFactoryBean
xxx.advice=MyAdvice
xxx.target=java.util.ArrayList
BeanFactory类
public class BeanFactory {
Properties props = new Properties();
public BeanFactory(InputStream ips){
props.load(ips);
}
public Object getBean(String name){
String className = props.getProperty(name);
Object bean = Class.forName(className).newInstance();
if(bean instanceof ProxyFactoryBean){
Object proxy = null;
ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
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();
return proxy;
}
return bean;
}
}
PoxyFactoryBean类
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 target) {
this.target = target;
}
public Object getProxy() {
// TODO Auto-generated method stub
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
/*new Class[]{Collection.class},*/
target.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
}
);
return proxy3;
}
}
Advice 接口封装想要添加的功能
public interface Advice {
void beforeMethod(Method method);
void afterMethod(Method method);
}