Java动态代理机制详解(JDK动态代理与CGLIB动态代理区别)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/RobertoHuang/article/details/71437046

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。在讲述动态代理前,我们先通过一个例子了解一下什么是静态代理,这里以事务控制为例。

1.静态代理

1.1 pom.xml文件配置

<properties>
    <!-- Spring -->
    <spring.version>4.1.3.RELEASE</spring.version>
</properties>
<dependencies>
    <!-- Spring Begin -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- Spring End -->
</dependencies>

1.2 业务接口代码

public interface UserService {
    /**
     * 
     * 功能描述: <br>
     * 〈保存用户〉
     *
     * @since [1.0.0](可选)
     */
    public void saveUser();

    /**
     * 
     * 功能描述: <br>
     * 〈更新用户〉
     *
     * @since [1.0.0](可选)
     */
    public void updateUser();
}

1.3 业务实现类代码

@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser() {
        System.out.println("userService saveUser()...");
    }

    @Override
    public void updateUser() {
        System.out.println("userService updateUser()...");
    }
}

1.4 事务管理类代码

@Service("transactionManager")
public class TransactionManager {
    public void beginTransaction() {
        System.out.println("开启事务....");
    }

    public void commint() {
        System.out.println("提交事务....");
    }

    public void rollback() {
        System.out.println("回滚事务....");
    }
}

1.5 代理类代码

@Service("userServiceProxy")
public class UserServiceProxy implements UserService {
    @Resource(name = "userService")
    private UserService userService;

    @Resource(name = "transactionManager")
    private TransactionManager transactionManager;

    @Override
    public void saveUser() {
        try {
            transactionManager.beginTransaction();
            userService.saveUser();
            transactionManager.commint();
        } catch (Exception e) {
            transactionManager.rollback();
        }
    }

    @Override
    public void updateUser() {
        try {
            transactionManager.beginTransaction();
            userService.updateUser();
            transactionManager.commint();
        } catch (Exception e) {
            transactionManager.rollback();
        }
    }
}

1.6 测试类代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ProxyTest {
    @Resource(name = "userServiceProxy")
    private UserService userService;

    @Test
    public void testStaticProxy() {
        userService.saveUser();
    }
}

1.7 测试结果

开启事务....
userService saveUser()...
提交事务....

从上面的代码,可以看出静态代理给我们带来的一系列问题,如在代理对象中包含了真实对象的引用,如果我们需要为不同的业务进行代理,就需要为每个业务都创建一个代理对象,甚是麻烦,所以引出了动态代理。

2.JDK动态代理

2.1 业务类接口

public interface UserService {
    /**
     * 
     * 功能描述: <br>
     * 〈保存用户〉
     *
     * @since [1.0.0](可选)
     */
    public void saveUser();

    /**
     * 
     * 功能描述: <br>
     * 〈更新用户〉
     *
     * @since [1.0.0](可选)
     */
    public void updateUser();
}

2.2 业务实现类

@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser() {
        System.out.println("userService saveUser()...");
    }

    @Override
    public void updateUser() {
        System.out.println("userService updateUser()...");
    }
}

2.3 事务管理类代码

@Service("transactionManager")
public class TransactionManager {
    public void beginTransaction() {
        System.out.println("开启事务....");
    }

    public void commint() {
        System.out.println("提交事务....");
    }

    public void rollback() {
        System.out.println("回滚事务....");
    }
}

2.4 代理类代码

@Service("transactionManagerProxy")
public class TransactionManagerProxy implements InvocationHandler {
    private Object target;

    @Resource(name = "transactionManager")
    private TransactionManager transactionManager;

    public Object createProxyObject(Object object) {
        this.target = object;
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        transactionManager.beginTransaction();
        Object object = null;
        try {
            object = method.invoke(target, args);
            transactionManager.commint();
        } catch (Exception e) {
            transactionManager.rollback();
        }
        return object;
    }
}

2.5 测试类代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ProxyTest {
    @Resource(name = "transactionManagerProxy")
    private TransactionManagerProxy transactionManagerProxy ;

    @Test
    public void testStaticProxy() {
        UserService userService = (UserService) transactionManagerProxy.createProxyObject(new UserServiceImpl());
        userService.saveUser();
    }
}

2.6 测试结果

开启事务....
userService saveUser()...
提交事务....

但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。

3.CGLIB动态代理

3.1 业务接口类

public interface UserService {
    /**
     * 
     * 功能描述: <br>
     * 〈保存用户〉
     *
     * @since [1.0.0](可选)
     */
    public void saveUser();

    /**
     * 
     * 功能描述: <br>
     * 〈更新用户〉
     *
     * @since [1.0.0](可选)
     */
    public void updateUser();
}

3.2 业务实现类

@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser() {
        System.out.println("userService saveUser()...");
    }

    @Override
    public void updateUser() {
        System.out.println("userService updateUser()...");
    }
}

3.3 事务管理类

@Service("transactionManager")
public class TransactionManager {
    public void beginTransaction() {
        System.out.println("开启事务....");
    }

    public void commint() {
        System.out.println("提交事务....");
    }

    public void rollback() {
        System.out.println("回滚事务....");
    }
}

3.4 事务代理类

public class TransactionManagerProxy implements org.springframework.cglib.proxy.InvocationHandler {
    private Object target;
    private TransactionManager transactionManager;

    public TransactionManagerProxy(Object target, TransactionManager transactionManager) {
        this.target = target;
        this.transactionManager = transactionManager;
    }

    // 创建代理对象
    public Object getProxyInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(this.getClass().getClassLoader());
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        transactionManager.beginTransaction();
        Object object = null;
        try {
            object = method.invoke(target, args);
            transactionManager.commint();
        } catch (Exception e) {
            transactionManager.rollback();
        }
        return object;
    }
}

3.5 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ProxyTest {
    @Resource(name = "transactionManager")
    private TransactionManager transactionManager;

    @Test
    public void testStaticProxy() {
        UserServiceImpl userServiceImpl = (UserServiceImpl) new TransactionManagerProxy(new UserServiceImpl(), transactionManager).getProxyInstance();
        userServiceImpl.saveUser();
    }
}

3.6 测试结果

开启事务....
userService saveUser()...
提交事务....

1.CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
2.要求类不能是final的,要拦截的方法要是非final,非static,非private的
3.动态代理的最小单位是类(所有类中的方法都会被处理)

注:若目标对象实现了若干接口,Spring就会使用JDK动态代理,若目标对象没有实现任何接口,Spring就使用CGLIB库生成目标对象的子类。

阅读更多
换一批

没有更多推荐了,返回首页