什么是java代理
代理是设计模式的一种,其原理就是通过代理对象去访问目标对象,而外部只能访问到代理对象
在编程中有这么一种思想,你不要随便的去修改已经写好的代码,如需修改,那么可以通过代理来扩展类的功能。
静态代理
什么是静态代理,静态代理就是你定义一个接口或者是父类,然后代理类与被代理类都需要继承这个接口,在代理类中实现一个方法,需要注入被代理类,这样就能通过代理类去访问被代理类,同时,也可以对被代理类进行增强。
上代码:
/**
* 定义一个接口,包含一个方法,吃
*/
public interface Person {
void eat();
}
/**
* 实现 Person
* 这个是一个实际的目标类,当前类实现一个吃的方法
*/
public class Man implements Person {
public void eat() {
System.out.println("吃饭");
}
}
/**
* Man对象的代理,当前代理持有一个Man的对象
*/
public class ManProxy implements Person {
private Person target;
public ManProxy(Person target){
this.target = target;
}
public void eat() {
System.out.println("吃冷菜");
target.eat();
System.out.println("吃甜品");
}
}
/**
* 测试
*/
public class App {
public static void main(String[] args) {
Person target = new Man();
Person manProxy = new ManProxy(target);
manProxy.eat();
}
}
结果:
吃冷菜
吃饭
吃甜品
以上就是一个典型的静态代理的例子,在当前的例子里,有一个Person的接口,该接口的主要作用是定义一个代理类和被代理类都拥有的行为,当前的行为为eat
代理类和被代理类都实现了Person,不过不同的是,代理类持有了一个被代理类的对象,在代理类中可以执行被代理类的方法,因此在代理类中可以在该方法的基础上进行扩展。
缺点:由于代理类需要实现与被代理类同一个接口,那么不同的被代理类就需要去实现不同的接口,那么就会出现代理类很难复用的情况,相对的维护成本也难以控制。
动态代理
什么是动态代理,动态代理就是利用JDK的API动态的在内存中构建代理对象,因此,动态代理也叫做JDK代理,或者接口代理,在动态代理中,代理对象不需要实现接口,但是被代理对象还是需要实现对象的。
生成代理对象的API
生成代理对象的API主要的包在java.lang.reflect.Proxy
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h )
参数说明:
ClassLoader loader : 该参数是被代理对象的使用的类加载器,这个我们直接通过被代理对象就可以获取
Class[] interfaces : 被代理对象实现的接口,这个也可以通过被代理对象获取
InvocationHandler h : 当我们在执行被代理对象的方法的时候,这个处理器就会被执行,当这个方法被执行的时候,会将被代理对象,方法,参数都传入进去
上代码:
/**
* 代理工厂
* 主要作用是生成代理对象
*/
public class ProxyFactory {
//被代理对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
//为被代理对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
//指定当前被代理对象使用的类加载器
target.getClass().getClassLoader(),
//指定被代理对象实现的接口类型,这里是一个数组,代理可能实现多个接口
target.getClass().getInterfaces(),
//事件处理,当我们在执行被代理对象的方法的时候,会触发这个处理器,会把当前执行的被代理对象的方法作为参数传入进去
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前置方法");
//执行目标方法
Object returnValue = method.invoke(target, args);
System.out.println("执行后置方法");
return returnValue;
}
}
);
}
}
public class App {
public static void main(String[] args) {
//被代理对象
Person target = new Man();
System.out.println("被代理对象打印:"+target.getClass());
//创建代理对象
Person proxy = (Person) new ProxyFactory(target).getProxyInstance();
System.out.println("代理对象打印:"+proxy.getClass());
proxy.eat();
}
}
结果:
被代理对象打印:class com.luban.aop.proxy.statics.Man
代理对象打印:class com.sun.proxy.$Proxy0
执行前置方法
吃饭
执行后置方法
缺点:在动态代理中,代理对象不需要再实现接口了,但是被代理对象还是需要实现接口,否则就无法使用动态代理
Cglib代理
什么是cglib代理,无论是动态代理还是静态代理,都要求我们的被代理的对象必须要实现某一个接口,但是也可能存在这样的情况,一个类没有实现任何的接口,这个时候就可以使用cglib代理。
cglib代理是通过被代理对象的子类的形式来实现代理的,他会在内存中构建一个被代理对象的子类对象,来实现对被代理对象的功能的扩展。
在cglib的底层是通过一个字节码处理框架ASM来转换字节码生成新的类
如果需要使用cglib的话,需要引入一个包 cglib
cglib
cglib
3.3.0
上代码
/**
* 被代理类
*/
public class Woman {
public void eat(){
System.out.println("吃饭");
}
}
/**
* cglib 代理工厂类
*/
public class ProxyFactory implements MethodInterceptor {
//被代理对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
//为被代理对象创建一个代理对象
public Object getProxyInstance(){
//这个是工具类
Enhancer en = new Enhancer();
//将被代理类设置为父类
en.setSuperclass(target.getClass());
//设置回调
en.setCallback(this);
//创建子类(代理对象)
return en.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("前置执行....");
//执行被代理类的方法
Object returnValue = method.invoke(target,objects);
System.out.println("后置执行....");
return returnValue;
}
}
public class App {
public static void main(String[] args) {
//被代理对象
Woman target = new Woman();
//代理对象
Woman proxy = (Woman) new ProxyFactory(target).getProxyInstance();
//执行方法
proxy.eat();
}
}
执行结果:
前置执行....
吃饭
后置执行....
注意:被代理对象的方法不能用final或者static
在springAOP中,如果被代理对象没有实现接口则使用cglib,如果实现了接口则使用动态代理
免费在线视频学习,请访问(持续更新中):java 教程 - 免费分享的视频教程
更多的资讯请访问QQ群:807167416