1.代理对象
定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用,从而实现对真实对象的操作。
通俗的来讲代理模式就是我们生活中常见的中介。
在代理模式中,代理对象主要起到一个中介的作用,用于协调与连接调用者(即客户端)和被调用者(即目标对象),在一定程度上降低了系统的耦合度,同时也保护了目标对象。 缺点是在调用者与被调用者之间增加了代理对象,可能会造成请求的处理速度变慢。
2.代理模式分为三类:
- 静态代理
- 动态代理
- CGLIB代理
结构图:
1.Subject:抽象角色,声明了真实对象和代理对象的共同接口;
2.Proxy:代理角色,实现了与真实对象相同的接口,所以在任何时刻都能够代理真实对象,并且代理对象内部包含了真实对象的引用,所以它可以操作真实对象,同时也可以附加其他的操作,相当于对真实对象进行封装。
3.RealSubject:真实对象,是我们最终要引用的对象
静态代理
静态代理模式由三个部分构成:
1.一个公共的接口
2.一个被代理角色
3.一个代理角色
1.创建公共的接口
//公共接口
public interface Rent {
void renting();
}
2.创建被代理角色
//被代理对象
public class Corey implements Rent{
//这是被代理对象!(房主)
@Override
public void renting() {
System.out.println("Corey有房出租");
}
}
3.创建代理角色
//代理对象(中介)
public class StaticProxyRent implements Rent{
private Rent rent;
public StaticProxyRent(Rent rent){
this.rent = rent;
}
@Override
public void renting() {
System.out.println("向房客出租房屋");
this.rent.renting();
System.out.println("完成售后服务");
}
}
- 创建测试类
public class StaticProxyTest {
public static void main(String[] args) {
Rent rent = new Corey();
StaticProxyRent staticProxyRent = new StaticProxyRent(rent);
staticProxyRent.renting();
}
}
- 使用 JDK 的 Proxy 类实现动态代理
1、 创建业务接口
public interface JdkProxyRent {
void renting();
}
2、 创建接口实现类
public class JdkProxyCorey implements JdkProxyRent {
@Override
public void renting() {
System.out.println("Corey 有房出租!");
}
}
- 创建生成代理对象的工厂
//动态生成代理对象的工厂
public class JdkProxyFactory {
//动态生成代理对象
public static Object getProxyBean(Object target){
Class clazz = target.getClass();
MyAspect myAspect = new MyAspect();
//在JDK中动态生成代理对象的方法
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
//动态生成代理对象的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
myAspect.before();
Object obj = method.invoke(target,args);
myAspect.after();
return obj;
}
});
}
}
4.创建切面对象
public class MyAspect {
public void before(){
System.out.println("带领房客看房...签租房协议");
}
public void after(){
System.out.println("售后服务");
}
}
5.创建测试类
public class jdkProxyTest {
public static void main(String[] args) {
JdkProxyRent jdkProxyRent = new JdkProxyCorey();
JdkProxyRent jdkProxyRent1 =(JdkProxyRent)JdkProxyFactory.getProxyBean(jdkProxyRent);
jdkProxyRent1.renting();
}
}
3.使用 CGLIB 实现动态代理
CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。因此 CGLIB 要依赖于 ASM 的包。
JDK 的动态代理机制只能代理实现了接口的类,而对于没有实现接口的类就不能使用JDK 的 Proxy 类生成代理对象,cglib 是针对类来实现代理的,他的原理是对指定的目标类生成一个子类并通过回调的方式来实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。
1.添加 jar 包
cglib.jar
asm.jar
2.创建业务接口
public interface CglibProxyRent {
void renting();
}
3.创建接口实现类
public class CglibProxyCorey implements CglibProxyRent {
@Override
public void renting() {
System.out.println("Corey 有房出租");
}
}
4.创建生成代理对象的工厂
public class CglibProxyBeanFactory {
public static Object getProxyBean(CglibProxyRent rent){
CglibMyAspect myAspect = new CglibMyAspect();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(rent.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
myAspect.before();
Object obj = method.invoke(rent,objects);
myAspect.after();
return obj;
}
});
return enhancer.create();
}
}
- 创建切面
public class CglibMyAspect {
public void before(){
System.out.println("带领客户看房,签订租房协议");
}
public void after(){
System.out.println("售后服务");
}
}
- 创建测试类
public class Test {
public static void main(String[] args) {
CglibProxyRent rent = new CglibProxyCorey();
CglibProxyRent rent1 = (CglibProxyRent) CglibProxyBeanFactory.getProxyBean(rent);
rent1.renting();
}
}