静态代理(定义一个平级的实现类完成代理模式)
动态代理
— JDK动态代理(定义拦截器实现InvocationHandler接口,通过Proxy产生代理对象)
—CGLIB动态代理(定义拦截器实现MethodInterceptor接口,通过Enhancer类生成代理对象)
代理对象和实际对象都继承了同一个接口,在代理对象中指向的是实际对象的实例,这样对外暴露的是代理对象而真正调用的是 Real Object.
静态代理就是通过创建平级的实现类的形式完成代理,能够实现代理的优势,但是同时缺点也很多:
以下就是基于静态代理进行的操作。静态代理存在如下几个缺点:
1、如果项目中存在N个接口,那么就会产生N个对应的实现类。我们的代理类也会随着实现类的增加而增加。
2、随着接口中的功能的增加,实现类中的功能也会同步增加。我们的代理类中的增强方法也会增加。
3、从严格意义上来讲:我们定义的增强的内容(事务处理)。其实是没有达到彻底复用。
4、优点:就是通过代理的方式,完成了目标对象的代理,并且在方法中置入了增强的处理,而且没有针对源代码进行修改。
package com.sin.service;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public interface ProxySubject {
public String inrtroduce(String name);
}
package com.sin.service.impl;
import com.sin.service.ProxySubject;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class ProxySubjectImpl implements ProxySubject {
@Override
public String inrtroduce(String name) {
System.out.println("我的名字是:" + name);
return name;
}
}
package com.sin.proxy;
import com.sin.service.ProxySubject;
import com.sin.service.impl.ProxySubjectImpl;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class StaticProxy implements ProxySubject {
private ProxySubjectImpl proxySubject;
public StaticProxy(ProxySubjectImpl proxySubject){
this.proxySubject = proxySubject;
}
@Override
public void inrtroduce(String name) {
System.out.println("调用前业务");
proxySubject.inrtroduce(name);
System.out.println("调用后的业务");
}
}
package com.sin.test.proxy;
import com.sin.proxy.StaticProxy;
import com.sin.service.ProxySubject;
import com.sin.service.impl.ProxySubjectImpl;
import org.junit.Test;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class StaticProxyTest {
@Test
public void test(){
ProxySubjectImpl proxySubject = new ProxySubjectImpl();
StaticProxy staticProxy = new StaticProxy(proxySubject);
staticProxy.inrtroduce("张三");
}
}

动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的· 过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
Java1.3 以后, JAVA 实现了动态代理技术,允许开发者在运行期创建接口的代理实例 。
JDK 的动态代理主要使用的是 java.lang.reflect 包中的Proxy 和 InvocationHandler。
//自定义定获取被代理接口实现类的实例对象
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
提示!
jdk动态代理必须要依赖于接口。
package com.sin.service;
/**
* 需要动态代理的接口
* @author sin
* @date 2022/10/27
* @apiNote
*/
public interface JDKAgentSubjectService {
/**
* 你好
* @param name
* @return
*/
public String sayHello(String name);
/**
* 再见
* @return
*/
public String sayGoodBye();
}
package com.sin.service.impl;
import com.sin.service.JDKAgentSubjectService;
/**
* 实例接口对象
*
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class JDKAgentSubjectServiceImpl implements JDKAgentSubjectService {
/**
* 你好
*
* @param name
* @return
*/
@Override
public String sayHello(String name) {
return "你好" + name;
}
/**
* 再见
*
* @return
*/
@Override
public String sayGoodBye() {
return "再见";
}
}
package com.sin.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class InvocationHandlerImpl implements InvocationHandler {
//要代理的对象
private Object subject;
public InvocationHandlerImpl(Object subject){
this.subject = subject;
}
/**
* 负责集中处理动态代理上的所有方法调用
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param args 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("模拟的添加操作");
System.out.println("Method" + method);
Object value = method.invoke(subject,args);
System.out.println("接收后模拟的添加操作");
return value;
}
}
package com.sin.test.proxy;
import com.sin.proxy.InvocationHandlerImpl;
import com.sin.service.JDKAgentSubjectService;
import com.sin.service.impl.JDKAgentSubjectServiceImpl;
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class InvocationHandlerTest {
@Test
public void testReal(){
//代理的对象
Object subjectService =new JDKAgentSubjectServiceImpl();
/**
* InvocationHandlerImpl 实现了InvocationHandler接口,实现方法调用从代理类到委托类的发派转发
* 内部包含了指向委托类实例的引用,用于真正执行分派转发过来的方法调用
* 要代理那个对象就将那个对象传进来,最后通过该对象来调用其方法
*/
InvocationHandler handler= new InvocationHandlerImpl(subjectService);
ClassLoader loader = subjectService.getClass().getClassLoader();
Class[] interfaces = subjectService.getClass().getInterfaces();
JDKAgentSubjectService subject = (JDKAgentSubjectService) Proxy.newProxyInstance(loader,interfaces,handler);
System.out.println("要动态代理对象的类型:"+subject.getClass().getName());
String hello = subject.sayHello("张三");
System.out.println(hello);
String bye = subject.sayGoodBye();
System.out.println(bye);
}
}

采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,来完成动态代理的实现。
实现方式实现 MethodInterceptor 接口,重写 intercept 方法,通过 Enhancer 类的回调方法来实现。
package com.sin.service;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public interface UserServiceCGlib {
public void addUser();
}
package com.sin.service.impl;
import com.sin.service.UserServiceCGlib;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class UserServiceCGlibImpl implements UserServiceCGlib {
@Override
public void addUser() {
System.out.println("增加了一条用户");
}
}
package com.sin.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* CGlib 动态代理实现类
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class MethodInterceptorImpl implements MethodInterceptor {
//CGlib需要代理的对象
private Object object;
public Object createProxyObject( Object o){
this.object = o;
//通过CGlib动态代理获取代理对象的过程
Enhancer enhancer = new Enhancer();
//设置Enhancer对象的父类
enhancer.setSuperclass(o.getClass());
//设置Enhancer的回顾对象
enhancer.setCallback(this);
//设置Enhancer对象的父类
Object o1 = enhancer.create();
return o1;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object obj ;
System.out.println("调用前的业务");
obj = method.invoke(object,objects);
System.out.println("调用后的业务");
return obj;
}
}
package com.sin.test.proxy;
import com.sin.proxy.MethodInterceptorImpl;
import com.sin.service.impl.UserServiceCGlibImpl;
import org.junit.Test;
/**
* @author sin
* @date 2022/10/27
* @apiNote
*/
public class MethodInterceptorTest {
@Test
public void test(){
UserServiceCGlibImpl userServiceCGlib = new UserServiceCGlibImpl();
MethodInterceptorImpl methodInterceptorimpl = new MethodInterceptorImpl();
UserServiceCGlibImpl serviceCGlib = (UserServiceCGlibImpl)methodInterceptorimpl.createProxyObject(userServiceCGlib);
serviceCGlib.addUser();
}
}

静态代理
JDK动态代理总结
动态代理类:在程序运行时,运用反射机制动态创建而成。
JDK的动态代理必须具备四个条件:1、目标接口 2、目标类 3、拦截器 4、代理类
CGLIB动态代理总结:
JDK代理和CGLib 代理区别