一,静态代理
代理的好处是:我们在调用时候,可以不用直接操作目标类,而是使用的代理类,使用代理类的好处是:我们可以对代理类添加一些额外的方法,这样就是对目标类进行了增强。代理有三个角色
1,抽象角色,是一个接口(或者抽象类),代理角色,和真实角色都要实现此接口。
2,真实角色:具备各种功能(方法)的一个类
3,代理角色:持有真实角色的引用(成员变量),还可以有自己的功能(方法)。
1,首先看的是抽象角色:CommonInterface.java
package proxy;
/**抽象角色:为一个接口或者抽象类,代理角色和真实角色都要实现此接口,这里以生产红酒来举例*/
public interface CommonInterface{
/** 生产红酒的方法 */
public void product();
/**销售红酒的方法*/
public void sell();
}
2,真实角色:RealObject.java
package proxy;
/**真实角色,实际上要完成的各种功能都是在此类中实现的*/
public class RealObject implements CommonInterface{
public void product(){
System.out.println("生产红酒。。。");
}
public void sell(){
System.out.println("销售红酒。。。");
}
}
3,代理角色:ProxyObject.java
package proxy;
/** 代理角色:实际上调用的时候调用的是代理角色,在代理角色内部,来调用真实角色的各种方法,真实角色对我们调用者来说是不可见的 */
public class ProxyObject implements CommonInterface{
private RealObject realObject = new RealObject();// 代理角色要持有真实角色的引用。这里为了方便直接在此处实例化new出对象,可以在此类的构造方法或者需要的地方实例化
@Override
public void product() {
before();//调用realObject.product()是我们的本来目的,这里我们还可以调用before()实际上是对product()方法进行增强了,提供了额外的功能。这里就是一个简单的AOP实现了
realObject.product();//可以看出就是在代理对象的方法的内部调用真实对象的方法的,
after();//功能同 before()
}
@Override
public void sell() {
before();
realObject.sell();
after();
}
/** 代理角色自己的方法 */
public void before() {
System.out.println("before....");
}
/** 代理角色自己的方法 */
public void after() {
System.out.println("after....");
}
}
4,客户端调用:ProxyTest.java
package proxy;
import static org.junit.Assert.*;
import org.junit.Test;
public class ProxyTest {
@Test
public void test() {
ProxyObject proxyObject=new ProxyObject();
proxyObject.product();//调用代理对象,可以看出我们想生产红酒,并没有调用 RealObject中的product()方法,
//而是通过代理对象来间接调用的,同时通过代理对象,还调用了before()after()等额外的方法
proxyObject.sell();
}
}
ProxyTest.java 输出
before....
生产红酒。。。
after....
before....
销售红酒。。。
after....
二,JDK动态代理
动态代理的对象必须要实现接口,换句话说只能代理实现接口的对象,和静态代理相比目标类需要实现接口,而代理类不需要实现接口
1,首先创建接口类:PersonService.java
package dynamicproxy;
public interface PersonService {
public void say(String word);
public void run(String speed,String where);
}
2,创建目标类PersonServiceImpl.java 实现以上接口
package dynamicproxy;
public class PersonServiceImpl implements PersonService {
@Override
public void say(String word) {
System.out.println("say..."+word);
}
@Override
public void run(String speed,String where) {
System.out.println("run..."+speed+where);
}
}
3,创建代理类ProxyFactoryBean.java,此代理类要实现InvocationHandler接口
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**代理类*/
public class ProxyFactoryBean implements InvocationHandler {
private Object obj;//代理类持有的对被代理对象的引用。(被代理对象)
/**
* 生成代理对象
* @param obj 从外部传入的被代理的对象
* @return 返回一个被代理好的对象(代理对象)
*/
public Object createProxyInstance(Object obj){
this.obj=obj;
//生成代理类的字节码加载器
ClassLoader loader=obj.getClass().getClassLoader();
//获得被代理对象obj的所有接口
Class<?>[] objInterfaces=obj.getClass().getInterfaces();
//返回生成的代理对象,这里要用到Proxy的方法,this表示InvocationHandler对象
return Proxy.newProxyInstance(loader, objInterfaces, this);
}
/**
* @param proxy 代理对象
* @param method 要调用的方法
* @param args 方法参数。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("开始。。。");
// 调用被代理类的方法,传入参数args,得到返回
//jdk动态代理是根据java反射来实现的,会根据入参的个数和类型,自动调用相应的方法
Object object=method.invoke(obj, args);
System.out.println("结束。。。");
return object;
}
}
4,创建测试类DynamicProxyTest.java
package dynamicproxy;
import static org.junit.Assert.*;
import org.junit.Test;
public class DynamicProxyTest {
@Test
public void test() {
ProxyFactoryBean proxyFactoryBean=new ProxyFactoryBean();
//返回代理对象
PersonService personService=(PersonService) proxyFactoryBean.createProxyInstance(new PersonServiceImpl());
//jdk动态代理是根据java反射来实现的,会根据入参的个数和类型,自动调用相应的方法
personService.say("hello word");
personService.run("20", "beijing");
}
}
5,输出为
开始。。。
say...hello word
结束。。。
开始。。。
run...20beijing
结束。。。