Java设计模式--代理模式+动态代理+CGLib代理
静态代理
抽象主题角色:声明真实主题和代理主题的共同接口。
代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象;代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代替真实主题。代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的传递调用。
真实主题角色:定义代理角色所代表的的真实对象。
UML图:
抽象主题
public interface Subject {void request();
}
真实主题
public class RealSubject implements Subject {@Override
public void request() {
System.out.println("真实对象的方法");
}
}
代理主题
public class ProxySubject implements Subject {private RealSubject subject;
public ProxySubject() {
}
@Override
public void request() {
pre();
if (subject == null){
subject = new RealSubject();
}
subject.request();
post();
}
private void pre(){
System.out.println("方法执行之前");
}
private void post(){
System.out.println("方法执行之后");
}
}
执行:
public static void main(String[] args) throws Exception {ProxySubject subject = new ProxySubject();
subject.request();
}
输出:
方法执行之前真实对象的方法
方法执行之后
动态代理
JDK自带的动态代理,实现InvocationHandler接口。
声明接口
public interface MyConnection extends AutoCloseable {void createStatement() throws Exception;
@Override
void close() throws Exception;
}
真实主题
public class MyDefaultConnection implements MyConnection {@Override
public void createStatement() throws Exception {
System.out.println("Create Statement ...");
}
@Override
public void close() throws Exception {
System.out.println("Close Connection ...");
}
}
代理主题
public class MyConnectionProxy implements InvocationHandler {private MyConnection conn;
private MyConnection proxyConn;
public MyConnectionProxy(MyConnection conn) {
this.conn = conn;
this.proxyConn = (MyConnection) Proxy.newProxyInstance(MyConnection.class.getClassLoader(), new Class<?>[] {MyConnection.class}, this);
}
public MyConnection getConn() {
return conn;
}
public MyConnection getProxyConn() {
return proxyConn;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
System.out.println("==代理方法:" + methodName);
if("close".equals(methodName)){
System.out.println("**不执行close方法");
}else{
return method.invoke(conn, args);
}
return null;
}
}
执行:
public static void main(String[] args) throws Exception {MyConnection connection = new MyDefaultConnection();
MyConnectionProxy proxy = new MyConnectionProxy(connection);
proxy.getProxyConn().createStatement();
proxy.getProxyConn().close();
}
你会发现我的代理对象去哪里了?实际上我放在InvocationHandler的实现类里面了,这里参考的是mybatis源码的设计。
输出:
==代理方法:createStatementCreate Statement ...
==代理方法:close
**不执行close方法
CGLib
CGLib不需要接口就能实现动态代理。
CGLIB 原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
CGLIB 底层:使用字节码处理框架ASM,来转换字节码并生成新的类。
<dependency><groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
需要代理的对象
public class Programmer {public void work(){
System.out.println("程序员正在敲代码...");
}
public final void finalCannotOverride(){
System.out.println("final方法不能被生成的子类覆盖");
}
private void privateCannotOverride(){
System.out.println("private方法不能被生成的子类覆盖");
}
}
代理类
public class ProgrammerProxy implements MethodInterceptor {// 真实对象
private Object realObject;
// 代理对象
private Object proxyObject;
public ProgrammerProxy(Object realObject) {
this.realObject = realObject;
Enhancer enhancer = new Enhancer();
// 设置需要代理的对象
enhancer.setSuperclass(realObject.getClass());
// 设置代理人
enhancer.setCallback(this);
this.proxyObject = enhancer.create();
}
public Programmer getProxyObject() {
return (Programmer) proxyObject;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
pre();
Object result = method.invoke(realObject, objects);
post();
return result;
}
private void pre(){
System.out.println("==先吃早餐");
}
private void post(){
System.out.println("==下班打卡");
}
}
执行:
public static void main(String[] args) throws Exception {Programmer programmer = new Programmer();
ProgrammerProxy proxy = new ProgrammerProxy(programmer);
proxy.getProxyObject().finalCannotOverride();
proxy.getProxyObject().work();
}
输出:
final方法不能被生成的子类覆盖==先吃早餐
程序员正在敲代码...
==下班打卡
以上是 Java设计模式--代理模式+动态代理+CGLib代理 的全部内容, 来源链接: utcz.com/z/392692.html