-
概念
代理模式:客户端直接使用的都是代理对象,不知道目标对象是谁,此时代理对象可以在客户端和目标对象之间起到中介的作用。
1、代理对象完全包含目标对象,客户端使用的都是代理对象的方法,和目标对象没有直接关系;
2、代理模式的职责:把不是目标对象该做的事情从目标对象上撇开——职责清晰; -
静态代理
在程序运行前就已经存在代理类的字节码文件,代理对象和目标对象的关系在运行前就确定了 -
动态代理
动态代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件。代理对象和真实对象的关系是在程序运行事情才确定的。 -
应用场景
这里做一个简单的事务代理实现; -
定义 一个注解,用来控制事务
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Inherited
public @interface Transactional {
String propagation() default "REQUIRED";
String isolation() default "DEFAULT";
}
- 定义jdkproxy
public class JDKProxy implements InvocationHandler {
private TransactionalManager transactionalManager = new TransactionalManager();
private Object targetClass;
public JDKProxy(Object targetClass) {
this.targetClass = targetClass;
}
public Object createProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), targetClass.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
//判断方法上是否包含transactional注解,如果有则执行事务,否则不执行
if(method.isAnnotationPresent(Transactional.class) || method.getDeclaringClass().isAnnotationPresent(Transactional.class)
||targetClass.getClass().isAnnotationPresent(Transactional.class)
|| targetClass.getClass().getMethod(method.getName(), method.getParameterTypes()).isAnnotationPresent(Transactional.class)){
try {
transactionalManager.begin();
obj = method.invoke(targetClass, args);
transactionalManager.commit();
} catch (Exception e) {
transactionalManager.rollback();
}
}else{
obj = method.invoke(targetClass, args);
}
return obj;
}
}
- 定义事务控制类
public class TransactionalManager {
public void begin(){
System.out.println("开启事务...");
}
public void commit(){
System.out.println("提交事务...");
}
public void rollback(){
System.out.println("回滚事务...");
}
}
- 定义service
public class TestServiceImpl implements TestService {
@Override
@Transactional
public String insert(String str) {
System.out.println("执行数据库操作逻辑");
return null;
}
}
- 定义测试类
public class Test {
public static void main(String[] args) {
//spring 加载bean
JDKProxy jdk = new JDKProxy(new TestServiceImpl());
//获取bean
TestService t = (TestService)jdk.createProxy();
//执行bean方法
t.insert("123");
}
}
打印结果:
开启事务...
执行数据库操作逻辑
提交事务...
git源码地址:https://gitee.com/xj-louge/pattern.git