事务注解是通过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、应用程序不直接进行服务的装配,但需要配置文件描述组件和服务的依赖关系,容器会自动装配他们。
原理:基于好莱坞原则--别来找我,我会去找你。也就是所有的组件都是被动的,组件的创建和装配都有容器来管理。