代理:
- 代理是什么?
代理就是在不修改源代码的情况下,对该类的方法进行扩展(增强)。
静态代理举例
interface ClothFactory{
void productCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory;
public ProxyClothFactory(ClothFactory factory) {
this.factory = factory;
}
@Override
public void productCloth() {
System.out.println("我是衣服代理类");
factory.productCloth();
System.out.println("代理工厂后续工作");
}
}
//被代理类
class NickClothFactory implements ClothFactory{
@Override
public void productCloth() {
System.out.println("Nick工厂生产衣服");
}
}
public class StaticProxy {
public static void main(String[] args) {
//创建被代理类
NickClothFactory nickClothFactory=new NickClothFactory();
//创建代理类
ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nickClothFactory);
proxyClothFactory.productCloth();
}
}
动态代理
动态代理主要是通过Proxy创建接口代理对象,所以首要问题就是如何通过Proxy创建接口代理对象。
创建接口代理对象主要使用的方法是:
- newProxyInstance(ClassLoad,Interfaces,InvocationHandler)
第一个参数:我们可以填写接口实现类的类加载器
第二个参数:实现类的实现接口
第三个参数:创建一个InvocationHandler接口的实现子类(增强方法在该子类里面)
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
这里通过一个demo学习:
OneDao:
public interface OneDao {
public int add(int a,int b);
}
OneDaoImpl:
public class OneDaoImpl implements OneDao {
@Override
public int add(int a, int b) {
return a+b;
}
}
我们的目的就是增强OneDaoImpl的add方法。
创建InvocationHandler 的实现子类:
class MyHandler implements InvocationHandler{
//传入被代理的实现类
private Object object;
public MyHandler(Object object){
this.object=object;
}
//增强方法逻辑
/**
*
* @param proxy :当前代理对象
* @param method:当前执行方法名称
* @param args :执行方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法前
System.out.println("方法前...."+method.getName());
//获得方法的第一个参数
System.out.println(args[0]);
//执行方法
Object res=method.invoke(object,args);
//方法后
System.out.println("方法后...."+method.getName());
return res;
}
}
获得代理对象:
@Test
public void method(){
OneDaoImpl oneDao=new OneDaoImpl();
OneDao dao = (OneDao) Proxy.newProxyInstance(OneDaoImpl.class.getClassLoader(), OneDaoImpl.class.getInterfaces(), new MyHandler(oneDao));
int add = dao.add(1, 2);
System.out.println(add);
}
(以下内容为之前所写,表达的不清楚)
interface Human{
int getAge();
String getName();
}
//被代理类
class GDPeople implements Human{
private int age;
private String name;
public GDPeople(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int getAge() {
return age;
}
@Override
public String getName() {
return name;
}
}
/**
要想实现动态代理,需要解决的问题:
1,如果根据加载到内存中的被代理类,动态创建一个代理类及其对象
2,当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法
*/
class ProxyFactory{
//调用此方法,返回一个代理类的对象。解决问题一
public static Object getProxyInstance(Object obj){//obj:被代理类的对象
MyInvocationHandler handler=new MyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}
class MyInvocationHandler implements InvocationHandler {
private Object object;//需要使用被代理类的对象进行赋值
public void bind(Object object){
this.object=object;
}
//当我们通过代理类的对象,调用方法a时,就会自动调用如下的方法:invoke()
//当被代理类要执行的方法a功能就声明在invoke()中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
System.out.println("代理之前");
//obj:被代理类的对象
Object invoke = method.invoke(object, args);
//上述方法的返回值就作为当前类中invoke()的返回值
System.out.println("代理之后");
return invoke;
}
}
public class ProxyTest {
public static void main(String[] args) {
GDPeople gdPeople=new GDPeople(15,"Tom");
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(gdPeople);
//当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
int age = proxyInstance.getAge();
String name = proxyInstance.getName();
System.out.println("name:"+name+"-----age:"+age);
}
}