两种:静态代理、动态代理。企业中,静态代理很少使用。
拦截的步骤可以被称为横截性关注点。
拦截某些类的话,会判断这个类是否实现了接口,如果实现了接口就会用 jdk 动态代理来创建代理对象;如果这个类没有实现接口情况下,则用 CGLIB 来创建代理对象。
jdk 动态代理:
package aop.test.factory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import output.test.impl.HelloBean;
public class JDKProxyFactory implements InvocationHandler {
private Object targetObject; // 代理的目标对象
public Object createProxyInstance(Object targetObject) {
this. targetObject = targetObject;
/*
* 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
* 第二个参数设置代理类实现的接口
* 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法
*/
return Proxy.newProxyInstance( this. targetObject.getClass().getClassLoader(),
this. targetObject.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HelloBean bean = (HelloBean) targetObject;
if( bean.getName()== null){ // 如果 name 是空,则不执行方法
return null;
}
return method.invoke( targetObject, args); // 把方法调用委派给目标对象
}
}
其中,被拦截的类 HelloBean :
package output.test.impl;
import output.test.Hello;
public class HelloBean implements Hello {
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HelloBean(){}
public HelloBean(String name) {
super();
this.name = name;
}
public void output() {
System.out.println("name="+name);
}
}
测试这个代理:
public void test() {
JDKProxyFactory proxy = new JDKProxyFactory();
Hello hello = (Hello) proxy.createProxyInstance( new HelloBean()); // 注册代理,返回参数的接口
hello.output(); // 调用这个接口中的任何函数时,都会触发代理中的 invoke()方法,判断是否要拦截
}