代理对象就是: 即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
1、静态代理
静态代理在使用时:需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。
实现步骤:
1、被代理对象实现接口或者基础父类。
2、代理对象与被代理对象一起实现相同的接口或者是继承相同父类。
3、代理对象的构造方法需要传入被代理对象的接口或者符父类。
4、在代理对象中调用被代理对象的方法,并且在调用前后可以加入自定义条件,作为前置增强和后置增强。
2、代理对象与被代理对象一起实现相同的接口或者是继承相同父类。
// 父类/接口
public interface Country {
void sayHello();
}
// 被代理对象
public class China implements Country {
@Override
public void sayHello() {
System.out.println("这里是中国");
}
}
// 代理对象
public class ChinaProxy implements Country {
private Country country;
public ChinaProxy(Country country) {
this.country = country;
}
@Override
public void sayHello() {
System.out.println("调用前");
country.sayHello();
System.out.println("调用后");
}
}
// 调用者
public class Main {
public static void main(String[] args) {
// 想要访问的对象,一个叫做China的国家
Country country = new China();
// 获取代理对象实例
ChinaProxy proxy = new ChinaProxy(country);
// 访问代理对象的具体方法
proxy.sayHello();
}
}
运行结果:
2、JDK动态代理
JDK动态代理只能对实现了接口的类进行代理,主要通过InvocationHandler接口、Proxy类实现。
步骤:
1、 被代理对象实现某个接口。
2、 代理对象实现InvocationHandler接口,代理对象的构造方法需要传入被代理对象的接口。
3、 在重写的invoke方法中,通过method.invoke()调用被代理对象的方法。
4、 在method.invoke()前后可以加入自定义条件,作为前置增强和后置增强。
5、调用者通过代理对象的Proxy.newProxyInstance()方法获取到被代理对象的实例。
// 接口
public interface Country {
void sayHello();
void sayName();
}
// 被代理对象
public class China implements Country {
@Override
public void sayHello() {
System.out.println("你好");
}
@Override
public void sayName() {
System.out.println("我是中国");
}
}
// 代理对象
public class ChinaProxy implements InvocationHandler {
private Country country;
public ChinaProxy(Country country) {
this.country = country;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用代理对象方法前的增强处理");
Object invoke = method.invoke(country, args);
System.out.println("调用代理对象方法后的增强处理");
return invoke;
}
public Object getInstance() {
return Proxy.newProxyInstance(country.getClass().getClassLoader(),
country.getClass().getInterfaces(), this);
}
}
// 调用者
public class Main {
public static void main(String[] args) {
// 想要访问的对象,一个叫做China的国家
Country country = new China();
// 要访问China必须要他的代理同意
ChinaProxy proxy = new ChinaProxy(country);
// 获取被代理对象实例
Country china = (Country) proxy.getInstance();
// 访问代理对象的具体方法
china.sayHello();
System.out.println("-------------");
china.sayName();
}
}
运行结果:
3、CgLib动态代理
Cglib动态代理:目标对象只是一个单独的对象没有实现接口或者基础父类,使用以目标对象子类的方式类实现代理,这种方法就叫做Cglib代理。
注意:
Spring AOP就是使用了cglib代理,使用时需要引入cglib.jar包,代理对象不能为final,目标对象的方法不能为final/static
步骤:
1、引入cglib jar包。
2、定义被代理对象。
3、代理对象实现MethodInterceptor接口,代理对象的构造方法,需要传入一个Object类型的被代理对象。
4、重写intercept方法,通过method.invoke()方法调用被代理对象的方法。
5、在method.invoke()前后可以加入自定义条件,作为前置增强或和后置增强。
6、调用者通过代理对象的Enhancer类创建子类代理对象实例。
//被代理对象
public class China {
public void sayHello() {
System.out.println("你好");
}
public void sayName() {
System.out.println("我是中国");
}
}
// 代理对象
public class ChinaProxy implements MethodInterceptor {
private Object target;
public ChinaProxy(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用前增强");
Object invoke = method.invoke(target, objects);
System.out.println("调用后增强");
return invoke;
}
public Object getInstance() {
//工具类
Enhancer en = new Enhancer();
//设置父类
en.setSuperclass(target.getClass());
//设置回调函数
en.setCallback(this);
//创建子类代理对象
return en.create();
}
}
// 调用者
public class Main {
public static void main(String[] args) {
// 想要访问的对象,一个叫做China的国家
China china = new China();
// 要访问China必须要他的代理同意
ChinaProxy proxy = new ChinaProxy(china);
// 获取子类代理对象实例
China chinaProxy = (China) proxy.getInstance();
// 访问代理对象的具体方法
chinaProxy.sayHello();
System.out.println("-------------");
chinaProxy.sayName();
}
}
运行结果:
4、三种代理方式区别
静态代理:在程序运行前,代理类的.class文件就已经存在了,事先知道目标对象是什么,一个代理对象就有实现一个接口。
动态代理类:在程序运行时,运用反射机制动态创建而成,只有在运行时才知道目标对象是什么。
静态代理:被代理对象需要实现接口或基础父类。
JDK动态代理:被代理对象需要实现接口。
CgLib代理:被代理对象为一个单独的对象。
动态代理好处:免于写重复的接口,更加关注方法的增强,降低了代码冗余。
5、AOP使用了那种代理模式
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理。
如果目标对象没有实现接口,用Cglib代理。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/17999.html