一:静态代理
1.概念
需要我们手写代理类,在程序运行前代理类已经存在。
注意:目标类和被代理类必须实现同一接口
2.实例
package com.zjt.test;
interface Duck {
void swim();
}
class DuckImpl implements Duck{
@Override
public void swim() {
System.out.println("小鸭子会游泳");
}
}
class ProxyDuck implements Duck{
Duck duck; //一个空的构造函数,且代理类中明确声明需要代理的目标对象
public ProxyDuck(){
this.duck=new DuckImpl();
}
@Override
public void swim() {
System.out.println("噶嘎嘎。。。");
duck.swim();
}
}
class Test{
public static void main(String[] args) {
Duck duck = new ProxyDuck();
duck.swim();
}
}
二:动态代理
1.概念
在运行时运用反射动态生成代理类。
注意:目标类必须实现接口
2.实例
目标类接口
public interface TargetInterface {
public void method1();
public String method2();
public int method3(int x);
}
目标类
public class Target implements TargetInterface{
@Override
public void method1() {
System.out.println("method1 running...");
}
@Override
public String method2() {
System.out.println("method2 running...");
return "method2";
}
@Override
public int method3(int x) {
return x;
}
}
动态代理测试类
public class ProxyTest3 {
@Test
public void test1() throws IllegalArgumentException, ClassNotFoundException{
//获得动态的代理对象---在运行时 在内存中动态的为Target创建一个虚拟的代理对象
//objProxy是代理对象 根据参数确定到底是谁的代理对象
TargetInterface objProxy=(TargetInterface)Proxy.newProxyInstance(
Class.forName("eProxy.Target").getClassLoader(), //与目标对象相同的类加载器
new Class[]{TargetInterface.class},
new InvocationHandler() {
@Override
//invoke 代表的是执行代理对象的方法
//method 代表目标对象的方法的字节码对象
//args 代表目标对象的相应方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("目标方法前的逻辑");
//执行目标对象方法
Object invoke = method.invoke(Class.forName("eProxy.Target").newInstance(), args);
System.out.println("目标方法后的逻辑");
return invoke;
}
}
);
objProxy.method1();
String method2 = objProxy.method2();
System.out.println(method2);
}
测试结果
3.应用场景
spring中的拦截器就是基于动态代理实现的。
三:CGLib代理
1.概念
①.第三方代理技术,cglib代理,可以对任何类生成代理。
②.代理的原理是对目标对象进行继承代理。
③.如果目标对象被final修饰,那么该类无法被cglib代理。
2.实例
目标类接口
public interface UserService {
void save();
void delete();
void update();
void find();
}
目标类
public class UserServiceImpl implements UserService{
@Override
public void save() {
System.out.println("保存用户");
//int i=1/0;
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("更新用户");
}
@Override
public void find() {
System.out.println("寻找用户");
}
}
CGLib代理类
public class UserServiceProxyFactory2 implements MethodInterceptor{
public UserService getUserServiceProxy(){
Enhancer en= new Enhancer(); //帮我们生成代理对象
en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理
en.setCallback(this); //代理要做什么
UserService us = (UserService) en.create();//创建代理对象
return us;
}
@Override
public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//打开事务
System.out.println("打开事务");
//调用原有方法
Object returnValue = methodProxy.invokeSuper(proxyObj, args);
//提交事务
System.out.println("提交事务");
return returnValue;
}
}
CGLibc测试类
public class Demo {
//测试cglib代理
@Test
public void func2(){
UserServiceProxyFactory2 factory2=new UserServiceProxyFactory2();
UserService usProxy = factory2.getUserServiceProxy();
usProxy.save();
//代理对象继承了被代理对象==》true
System.out.println(usProxy instanceof UserServiceImpl);//true
}
}
测试结果
3.应用场景
springaop会使用CGLib代理当然被代理类有接口的情况下会优先使用动态代理。