由事务注解引起的代理相关

事务注解是通过spring aop代理实现

大致步骤是:
1、caller -》 aop 代理对象
2、aop代理对象的事务增强
3、代理interceptor 其他增强
4、执行目标对象的目标方法
5、按照4-》1 返回

代理:
aop代理 AopUtils.isAopProxy(bean)
cglib代理 AopUtils.isCglibProxy(bean)
java动态代理 AopUtils.isJdkDynamicProxy(bean)

问题:

    public interface TestServiceImpl implements TestService{
        @Transactional
        public void a(){
            this.b();
        }
        @Transactional
        public void b(){

        }
    }
当a中调用b时,b的事务没有执行,因为a调用b直接走步骤4,而不是通过aop代理的方式

解决方法:
调用方法改为:aopProxy.b();

1.通过ThreadLocal方法暴露Aop代理对象
    <aop:aspectj-autoproxy expose-proxy="true"/>
2.this.b()  ---->     ((TestService)AopContext.currentProxy()).b();

其他方法:
1、将本身注入;或者 实现BeanPostProcessor 接口实现自身代理对象的注入;
注解:将本身注入的方式不适用于循环依赖的两个对象,如果循环依赖,注入的可能不是代理对象,而是目标对象本身,达不到代理的目的;

AOP 相关

1、问题
针对同一类方法增加 同一类的日志记录、监控、安全监测等

2、解决方法
2.1 直接增加在方法里;--- 重复,紧耦合
2.2 抽象类共性设计,子类个性化设计;--- 一荣俱荣一损俱损
2.3 装饰器/代理模式设计;--- 紧耦合,每个实现类需要一个代理对象
2.4 动态代理(不适用于final类)

    2.4.1 java动态代理---接口
             @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                Object retVal = null;
                boolean ok = true;
                // 代理方法之前的处理:条件判断,日志,权限等
                if (!ok) {
                    throw new RuntimeException("权限等");
                } else {
                    // 反射调用目标对象的方法
                    method.invoke(target, args);
                }
                // 此处可以是 目标对象方法之后的后处理
                return retVal;
            }
    2.4.2 cglib动态代理---接口和类
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object resVal = null;
                /**
                 * 预处理
                 */
                boolean ok = true;
                if (!ok) {
                    throw new RuntimeException("没有权限");
                } else {
                    resVal = methodProxy.invoke(target, objects);
                }
                /**
                 * 代理后处理
                 */
                return resVal;
            }
    动态代理本质:对目标对象增强;
    代理限制:只能在父类方法调用之前或之后进行增强,不能在中间进行修改,想要在中间进行修改,需要ASM(java 字节码生成库);

2.5 Aop 代理
        @Aspect
        public class AopTest {
            @Pointcut(value = "execution(* *(..))")
            public void pointCut() {}
    
            @Around(value = "pointCut()")
            public Object around(ProceedingJoinPoint pjp) throws Throwable {
                Object retVal = null;
                /**
                 * 前置处理...
                 */
                retVal = pjp.proceed();
                /**
                 * 后置处理...
                 */
                return retVal;
            }
        }
    AOP缺点:依赖aop框架;

3、aop 关注点.
关注点:所关注的任何东西;-- 需要被增强的各种方法;
关注点分离:将问题划分为不可分割的单独部分,单一独立的模块;
横切点分离:会在多个模块中出现,跨越多个模块;一定要独立,松耦合,可以随意组合使用。
织入:横切点分离之后,需要通过某种技术,将很切点融入到系统中,以完成需要的功能,因此需要织入。织入可能在编译期、加载器或运行期等进行。

AOP 关注与业务无关,但是却被各模块公用的逻辑或功能,例如,日志管理、权限控制、事务处理等,封装起来,减少重复代码,减少模块之间的耦合度。

AOP代理(AOP Proxy):
AOP框架使用代理模式创建的对象,从而实现在连接点处插入增强(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。默认使用jdk动态代理。

IOC/DI

- IOC (inversion of control)控制反转
    定义:控制权从应用转移到框架(实现了IOC思想的容器成为IOC容器)

    对象的创建过程:
        1、创建对象
        2、实例化(主动、被动)
        3、依赖关系 (直接、间接)
        4、装配 (主动、被动)
    创建可以由应用程序主动进行,完成1-4;也可以将2-4交由框架进行,使用的时候框架已经准备好了,可以直接使用;
    对象创建的控制权转移到了框架,这就是IOC。
    ==> 建立a对象,需要b属性,则通过反射创建b对象,装配到a对象中。

    ps:容器提供组件运行环境 + 管理组件生命周期
    IOC容器=容器+依赖装配

- DI(Dependency Injection)依赖注入
    用一个单独的对象(装配器IOC容器)来装配对象之间的依赖关系。
    注入方式:构造器注入、setter方式注入、接口注入等。

备注:IOC/DI 的开发思路
    1、应用程序不主动创建对象,但需要描述创建他们的方式;
    2、应用程序不直接进行服务的装配,但需要配置文件描述组件和服务的依赖关系,容器会自动装配他们。
    原理:基于好莱坞原则--别来找我,我会去找你。也就是所有的组件都是被动的,组件的创建和装配都有容器来管理。

猜你喜欢

转载自www.cnblogs.com/paxing/p/10430647.html