您的位置:首页 > 编程语言 > Java开发

spring,静态代理和动态代理(jdk和cglib方式)示例

2020-01-15 11:53 239 查看

基于maven项目,pom.xml的配置:

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.1.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>

实体类的代码:此处只是模拟数据库插入数据,但是并没有真正的插入数据。故实体类比较简单。

package com.bean;

public class Employee {
}

dao层:
EmployeeDao.java

package com.dao;

import com.hpeu.bean.Employee;

public interface EmployeeDao {
public void save(Employee employee);
public void update(Employee employee);
}

dao实现层:
EmployeeDaoImpl.java

package com.dao;

import com.bean.Employee;

public class EmployeeDaoImpl implements EmployeeDao {

@Override
public void save(Employee employee) {
System.out.println("保存员工");
}

@Override
public void update(Employee employee) {
System.out.println("修改员工");
}
}

service层:
EmployeeService.java

package com.service;

import com.bean.Employee;

public interface EmployeeService {
public void save(Employee emp);
public void update(Employee emp);
public Employee getEmployeeById(Integer id);
}

service实现层:
EmployeeServiceImpl.java

package com.service.impl;

import com.bean.Employee;
import com.dao.EmployeeDao;
import com.service.EmployeeService;

public class EmployeeServiceImpl implements EmployeeService {
private EmployeeDao dao;

public void setDao(EmployeeDao dao) {
this.dao = dao;
}

@Override
public void save(Employee emp) {
//System.out.println("开启事务");
//try {
dao.save(emp);
//System.out.println("提交事务");
//} catch (Exception e) {
//e.printStackTrace();
//System.out.println("回滚事务");
//} finally {
//System.out.println("释放资源");
//}//此处太繁琐了,需要封装成一个类
}

@Override
public void update(Employee emp) {
dao.update(emp);
throw new RuntimeException("出错了。。。。");
}
}

模拟事务管理器:
TransactionManager.java

package com.service.impl;

// 模拟事务管理器
public class TransactionManager {
public void begin() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
public void rollback() {
System.out.println("回滚事务");
}
}

静态代理层:
StaticProxyService。java

package com.proxy;

import com.bean.Employee;
import com.service.EmployeeService;
import com.service.impl.TransactionManager;

/**
*  静态代理类
* 静态代理类需要有真实对象的引用,因代理对象中的核心方法还是真实对象来完成。
*/
public class StaticProxyService {
private EmployeeService target; // 真实对象
private TransactionManager txManager; // 代理对象

public void setTarget(EmployeeService target) {
this.target = target;
}

public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}

public void save(Employee emp) {
txManager.begin();
try {
target.save(emp);
txManager.commit();
} catch (Exception e) {
e.printStackTrace();
txManager.rollback();
}
}

public void update(Employee emp) {
txManager.begin();
try {
target.update(emp);
txManager.commit();
} catch (Exception e) {
txManager.rollback();
System.out.println(e.getMessage());
}
}
}

jdk动态代理层:
JdkDyniProxy.java

package com.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.service.impl.TransactionManager;

/**
* JDK动态代理
* 前提条件:
* 	真实对象(被代理对象)必须实现至少一个接口。
*
* 实现方法:
* 需要使用java.lang.reflect.Proxy类,然后使用该类中的newProxyInstantce()方法来
* 实例化代理对象。
* 同时,还需要有一个实现了java.lang.reflcet.InvocationHandler接口的类。因为
* 在执行代理对象时,系统自动会调用被代理对象的invoke方法。
*/
public class JdkDyniProxy implements InvocationHandler {
// 定义被代理对象
private Object target;
private TransactionManager txManager; // 事务管理器

public void setTarget(Object target) {
this.target = target;
}
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}

/*
public JdkDyniProxy(Object target) {
this.target = target;
}
*/

// 通过动态代理的方式来创建真实对象
public Object create() {
/**
* 参数说明:
* ClassLoader loader:被代理对象(真实对象)的类装载器
* Class<?>[] interfaces:被代理对象实现的接口类的数组
* InvocationHandler h:实现了InvocationHandler的对象
*/
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}

/**
* proxy:代理对象
* method:被执行的真实对象中的方法名称
* args:被执行的真实对象中方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
txManager.begin();
try {
System.out.println("-------" + method.getName());
result = method.invoke(target, args);
txManager.commit();
} catch (Exception e) {
txManager.rollback();
System.out.println(e.getMessage());
}
return result;
}
}

cglib动态代理
CGLIBDynamicProxy.java

package com.proxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;

import com.service.impl.TransactionManager;

/**
* 使用CGLIB实现动态代理
* 从Spring5.X开始,CGLIB已经被纳入到官方spring-core.jar包中,以之前的版本中
* 需要引入cglib的jar文件才能使用。
* cglib实现的动态代理的对象不需要实现接口。
*/
public class CGLIBDynamicProxy implements InvocationHandler {
private Object target; // 被代理对象(真实对象)
private TransactionManager txManager;

public void setTarget(Object target) {
this.target = target;
}
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}

// 创建代理对象
public Object create() {
Enhancer enhancer = new Enhancer();
// 设置被代理对象的父类
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create(); // 创建代理对象
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if (name.startsWith("get") || name.startsWith("find")) {
return method.invoke(target, args);
}

Object result = null;
txManager.begin();
try {
System.out.println("=======" + name);
result = method.invoke(target, args);
txManager.commit();
} catch (Exception e) {
txManager.rollback();
System.out.println(e.getMessage());
}
return result;
}
}

spring配置类:
beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="txManager" class="com.service.impl.TransactionManager"/>

<bean id="employeeDao" class="com.dao.EmployeeDaoImpl" />

<!-- 配置静态代理 -->
<bean id="staticProxy" class="com.proxy.StaticProxyService">
<property name="txManager" ref="txManager" /><!--ref表示对另一个类的引用 -->
<property name="target">
<bean class="com.service.impl.EmployeeServiceImpl">
<property name="dao" ref="employeeDao"/>
</bean>
</property>
</bean>

<!-- 配置JDK动态代理 -->
<bean id="jdkDyniProxy" class="com.proxy.JdkDyniProxy">
<property name="target">
<bean class="com.service.impl.EmployeeServiceImpl">
<property name="dao" ref="employeeDao" />
</bean>
</property>
<property name="txManager" ref="txManager" />
</bean>

<!-- 配置CGLIB动态代理 -->
<bean id="cglibProxy" class="com.hpeu.proxy.CGLIBDynamicProxy">
<property name="target">
<bean class="com.hpeu.service.impl.EmployeeServiceImpl">
<property name="dao" ref="employeeDao" />
</bean>
</property>
<property name="txManager" ref="txManager" />
</bean>
</beans>

Jdk动态代理测试类
JdkDyniProxyTest.java

package com.test.dyni.proxy;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import com.bean.Employee;
import com.proxy.JdkDyniProxy;
import com.service.EmployeeService;

/**
* Jdk动态代理测试类
*/
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class JdkDyniProxyTest {
@Autowired
private JdkDyniProxy jdkDyniProxy;

@Test
public void testSave() {
EmployeeService obj = (EmployeeService) jdkDyniProxy.create();
obj.save(new Employee());
//System.out.println(obj);
}
@Test
public void testUpdate() {
EmployeeService obj = (EmployeeService) jdkDyniProxy.create();
obj.update(new Employee());
}

/*
@Test
public void testXx() {
EmployeeService obj = (EmployeeService) new JdkDyniProxy(new EmployeeServiceImpl()).create();
obj.update(new Employee());
}
*/
}

cglib动态代理测试类
CGLIBDynamicProxyTest.java

package com.test.dyni.proxy;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import com.bean.Employee;
import com.proxy.CGLIBDynamicProxy;
import com.service.EmployeeService;

// CGLIB动态代理测试类
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class CGLIBDynamicProxyTest {
@Autowired
private CGLIBDynamicProxy cglibDyniProxy;

@Test
public void testSave() {
EmployeeService obj = (EmployeeService) cglibDyniProxy.create();
String name = obj.getClass().getName();
System.out.println(name);
obj.save(new Employee());
}

@Test
public void testUpdate() {
EmployeeService obj = (EmployeeService) cglibDyniProxy.create();
obj.update(new Employee());
}

@Test
public void testXx() {
EmployeeService obj = (EmployeeService) cglibDyniProxy.create();
obj.getEmployeeById(2);
}
}

静态代理测试类
ProxyStaticTest.java

package com.test.statics.proxy;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import com.bean.Employee;
import com.proxy.StaticProxyService;

// 静态代理测试类
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class ProxyStaticTest {
@Autowired
private StaticProxyService serviceProxy;

@Test
public void testSave() {
serviceProxy.save(new Employee());
}
@Test
public void testUpdate() {
serviceProxy.update(new Employee());
}
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
一梦如意 发布了92 篇原创文章 · 获赞 1 · 访问量 1013 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐