静态代理:
1、代理对象和目标对象都要实现的 公共接口
2、代理对象持有目标对象引用,重写构造方法,
3、实现共同的方法,代理对象增强行为。
缺点:
代理角色固定,一次只能代理一个对象。
接口
public interface Marry {
void marry();
}
目标对象
public class You implements Marry {
public void marry() {
System.out.println("sihai get marry");
}
}
代理对象
public class MarryCompany implements Marry {
private You you;
public MarryCompany(You you) {
this.you = you;
}
public void marry() {
before();
you.marry();
after();
}
private void after() {
System.out.println("get after work done");
}
private void before() {
System.out.println("get ready for marry");
}
}
测试
public class TestMarry {
public static void main(String[] args) {
You you = new You();
MarryCompany marryCompany = new MarryCompany(you);
marryCompany.marry();
}
}
结果
get ready for marry
sihai get marry
get after work done
动态代理
根据需要通过反射机制在程序运行期动态的为目标对象创建代理对象,代理的行为可以代理多个方法,即满足生产需要的同时又达到代码的通用目的。
动态代理有两种实现方法:JDK方式和cglib方式。
区别
jdk动态代理的目标对象必须有接口,且创建的代理对象也是需要转化成接口类型去执行方法,达到增强目标对象行为的目的。这个过程制作快,执行慢。
cglib动态代理以 继承 来实现,主要解决没有接口类的代理实现。 这个过程制作慢,执行快。
JDK动态代理:
接口Marry和目标对象You不变
动态代理类
/**
* JDK动态代理:
* 1. 目标对象要有接口,且最后创建的代理对象要转换成此接口类型,来调用方
* 2. 动态代理类实现InvocationHandler接口,持有目标对象引用,利用构造器动态传入目标对象
* 3. 使用proxy.newProxyInstance()来动态地创建代理对象
* 4. 代理对象重写invoke方法,利用反射调用目标对象的方法,同时增加行为
*/
public class JDKHandler implements InvocationHandler {
//目标对象引用
private Object target;
//构造器,可以动态传入目标对象
public JDKHandler(Object target) {
this.target = target;
}
//创建代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//利用反射机制调用目标对象的方法,并增强行为
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target,args);
after();
return result;
}
private void after() {
System.out.println("get after work done");
}
private void before() {
System.out.println("get ready for marry");
}
}
测试
public class MarryTest { public static void main(String[] args) { //动态代理类,利用构造器传入目标对象
//创建代理对象 Marry marryProxy = (Marry) jdkHandler.getProxy(); //代理对象调用方法,会增加目标对象的行为 marryProxy.marry(); }}JDKHandler jdkHandler = new JDKHandler(new You());
cgib动态代理
目标对象无要求,最后创建的动态代理会转换成此目标对象类型,去调用方法实现行为增强。
/**
* cglib动态代理
* 1. 目标对象
* 2. 实现MethodInterceptor接口,持有目标对象引用,利用构造器动态传入目标对象
* 3. 重写intercept方法,实现行为增强
*/
public class CglibInterceptor implements MethodInterceptor {
//目标对象
private Object target;
//构造器
public CglibInterceptor(Object target){
this.target=target;
}
//动态创建代理对象
public Object getProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
//行为增强
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
after();
Object result = methodProxy.invoke(target,objects);
return result;
}
private void after() {
System.out.println("after");
}
private void before() {
System.out.println("before");
}
}
目标对象
public class Hello {
public void print(){
System.out.println("hello");
}
}
测试
public class Test {
public static void main(String[] args) {
//动态代理类
CglibInterceptor cglibInterceptor = new CglibInterceptor(new Hello());
//创建代理,且需要转换成目标对象类型
Hello proxy = (Hello) cglibInterceptor.getProxy();
//代理对象调用方法,行为会得到增强
proxy.print();
}
}