spring5整理:(六)CGLIB动态代理-模拟事务

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

使用JDK的动态代理,只能针对目标对象存在接口的情况,如果目标对象没有接口,此时可以考虑使用CGLIB动态代理方式。

CGLIB是通过生成代理类,然后继承于目标类,再对目标类中可以继承的方法做覆盖,并在该方法中做功能增强,因为多态的关系,实则调用的是子类中的方法

1.xml配置:与JDK动态代理时一样

<bean id="employeeDAO" class="com.bigfong.dao.impl.EmployeeDAOImpl" />

<bean id="transactionManager" class="com.bigfong.tx.TransactionManager" />

<bean id="employeeService" class="com.bigfong.service.impl.EmployeeServiceImpl">
	<property name="dao" ref="employeeDAO" />
</bean>


<!-- 配置一个事务增强的类 -->
<bean id="transactionManagerAdvice" class="com.bigfong.tx.TransactionManagerAdvice">
	<property name="target" ref="employeeService"/>
	<property name="txManager" ref="transactionManager"/>
</bean>

2.EmployeeServiceImpl类不需要实现接口

3.TransactionManager类:与JDK动态代理时一样

//模拟事务管理器:
public class TransactionManager {

	public void begin() {
		System.out.println("开启事务");
	}

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

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

4.TransactionManagerAdvice事务的增强类

@SuppressWarnings("all")
//事务的增强操作-CGLIB
public class TransactionManagerAdvice implements org.springframework.cglib.proxy.InvocationHandler {

	private Object target;//真实对象(对谁做增强)
	private TransactionManager txManager;//事务管理器(模拟)

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

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

	//创建一个代理对象
	public <T> T getProxyObject() {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());//将继承于哪一个类,去做增强
		enhancer.setCallback(this);//设置增强的对象
		return (T) enhancer.create();//创建代理对象
	}

	//如何为真实对象的方法做增强的具体操作
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object ret = null;
		txManager.begin();
		try {
			//---------------------------------------------------------------
			ret = method.invoke(target, args);//调用真实对象的方法
			//---------------------------------------------------------------
			txManager.commit();
		} catch (Exception e) {
			e.printStackTrace();
			txManager.rollback();
		}
		return ret;
	}
}

增强类与使用JDK代理方式时的不同

1)增强类实现的类不同,实现的是org.springframework.cglib.proxy.InvocationHandler

2)创建一个代理对象方式不同

 

5.调用

@Autowired
private TransactionManagerAdvice advice;

//JDK代理对象:com.sun.proxy.$Proxy19
//CGLIB代理对象:com.bigfong.service.impl.EmployeeServiceImpl$$EnhancerByCGLIB$$c0c52615
@Test
void testSave() throws Exception {
	EmployeeServiceImpl proxy = advice.getProxyObject();
	proxy.save(new Employee());
}

@Test
void testUpdate() throws Exception {
	EmployeeServiceImpl proxy = advice.getProxyObject();
	proxy.update(new Employee());
}

总结:

1.CGLIB可以生成委托类的子类,并重写父类非final修饰的方法

2.要求类不能是final的,要拦截的方法要是非final,非static,非private的

3.动态代理的最小单位是类(类中所有的方法都会被处理)

 

代理选择要点

1.JDK动态代理是基于实现接口的,CGLIB和Javassit是基于继承委托的

2.性能上:Javassit > CGLIB > JDK

3.对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统,也更符合面向接口编程规范

4.若委托对象实现了接口,优先选用JDK动态代理

5.若委托对象没有实现任何接口,使用Javassit和CGLIB动态代理

 

上一篇:spring5整理:(五)JDK动态代理-模拟事务

下一篇:spring5整理:(七)AOP 

 

展开阅读全文

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