代理模式:客户端直接使用的都是代理对象,不知道真实对象是谁,此时代理对象可以在客户端和真实对象之间起中介作用。
1.代理对象完全包含真实对象,客户端使用的都是代理对象的方法,和真实对象没有直接关系
2.代理模式的职责:把不是真实对象该做的事情从真实对象上提取出来————职责分明;
静态代理:在程序运行前就已经存在代理类的字节码文件,代理对象和真实对象的关系在运行前就确定了。
代码演示
1.domain包
//就一个超级简单的Employee类
package com.keen.proxy.domain;
public class Employee {
}
2.dao包中的类
//(1)dao接口(增删改查)
package com.keen.proxy.dao;
import com.keen.proxy.domain.Employee;
public interface EmployeeDAO {
public void save(Employee e);
public void update(Employee e);
}
//dao的实现类
package com.keen.proxy.dao;
import com.keen.proxy.domain.Employee;
public class EmployeeDAOimpl implements EmployeeDAO{
public void save(Employee e) {
System.out.println("保存操作");
}
public void update(Employee e) {
System.out.println("更新操作");
}
}
3.service包
// IEmployeeService 接口(代理接口:由代理和真正的主人去实现)
package com.keen.proxy.service;
import com.keen.proxy.domain.Employee;
public interface IEmployeeService {
void save(Employee e);
void update(Employee e);
}
//IEmployeeServiceImpl (主人真实类)
package com.keen.proxy.service;
import com.keen.proxy.dao.EmployeeDAO;
import com.keen.proxy.domain.Employee;
//真实类(委托对象)
public class IEmployeeServiceImpl implements IEmployeeService{
private EmployeeDAO dao;
public void setDao(EmployeeDAO dao) {
this.dao = dao;
}
public void save(Employee e) {
dao.save(e);
System.out.println("保存成功");
}
public void update(Employee e) {
dao.update(e);
//为了演示事务回滚,故意出错
throw new RuntimeException("故意出错");
}
}
4.tx包中的事务类(TransactionManager)
package com.keen.proxy.tx;
//模拟事务管理器
public class TransactionManager {
public void begin() {
System.out.println("开启事务");
}
public void commit() {
System.out.println("提交事务");
}
public void rollback() {
System.out.println("回滚事务");
}
}
5.proxy包
package com.keen.proxy.proxy;
//静态代理类
import com.keen.proxy.domain.Employee;
import com.keen.proxy.service.IEmployeeService;
import com.keen.proxy.tx.TransactionManager;
public class IEmployeeServiceProxy implements IEmployeeService
{
private IEmployeeService targer;//真实对象/委托对象
private TransactionManager txManager;//事务管理器
public void setTarger(IEmployeeService targer) {
this.targer = targer;
}
public void setTxManager(TransactionManager txManager) {
this.txManager = txManager;
}
public void save(Employee e) {
//事务操作
txManager.begin();
try {
targer.save(e);
txManager.commit();
} catch (Exception e1) {
e1.printStackTrace();
txManager.rollback();
}
}
@Override
public void update(Employee e) {
//事务操作
txManager.begin();
try {
targer.update(e);
txManager.commit();
} catch (Exception e1) {
e1.printStackTrace();
txManager.rollback();
}
}
}
(6).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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- di注解解析器 -->
<!-- <context:annotation-config/> -->
<!--IOC注解解析器 -->
<!-- <context:component-scan base-package="com.keen.proxy"/> -->
<bean id = "employeeDAO" class = "com.keen.proxy.dao.EmployeeDAOimpl"/>
<!-- 事务管理器 -->
<bean id = "transactionManager" class = "com.keen.proxy.tx.TransactionManager"/>
<!-- 代理对象 -->
<bean id = "employeeServiceProxy" class = "com.keen.proxy.proxy.IEmployeeServiceProxy" >
<property name="txManager" ref ="transactionManager"/>
<property name="targer" >
<!-- 把employeeService作为内部bean -->
<bean class ="com.keen.proxy.service.IEmployeeServiceImpl">
<property name = "dao" ref = "employeeDAO"/>
</bean>
</property>
</bean>
</beans>
(7)测试类
package com.keen.proxy;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.keen.proxy.domain.Employee;
import com.keen.proxy.service.IEmployeeService;
@SpringJUnitConfig
public class AutoTest {
@Autowired
private IEmployeeService service;
@Test
void testSave() throws Exception {
service.save(new Employee());
}
@Test
void testUpdate() throws Exception {
service.update(new Employee());
}
}
静态代理的优缺点
1.优点:
(1)让业务类只需要关注业务逻辑
(2) 把真实对象隐藏起来了,保护了真实对象
2.缺点:
(1)代理对象的某个接口只能服务于某一种类型的对象,也就是说每一个真实的对象有得创建一个代理对象
(2)如果需要代理的方法很多,则要为每一种方法都进行代理处理
(3)如果接口增加一个方法,除了所有实现类需要实现这个方法外,代理类也需要实现此方法。
网友评论