写在前面
Spring-AOP
Aspect Orienter Programming,面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
- 对业务逻辑的各个部分进行隔离,使业务逻辑各部分耦合度降低,处理业务层的互相引用
- 抽取方法,通过AOP通过配置方式进行结合,在运行期间,结合不同的业务方法
- 底层通过
动态代理进行实现,在运行期间,spring通过动态代理技术生成代理对象,代理对象执行时进行增强方法的切面介入
- 动态代理
JDK基于接口的动态代理技术;cglib代理,基于父类的动态代理技术
- spring根据目标类是否实现了接口来决定采用哪种动态代理方式
- 动态代理其实就是在原来的方法上增加了新的内容,产生了一个新的子类
AOP术语
- Target 目标对象,代理的目标对象
- Proxy 一个类被AOP织入增强后,产生一个新的结果代理类
- Joinpint 连接点,可以被增强的方法
- Pointcut 切入点,真正被增强处理后的方法
- Advice 通知/增强,增强切入点的方法
- Aspect 切面,切点+增强/通知
- Weaving 织入,将增强和切点结合的过程
JDK实现动态代理
- 需要接口,接口实现类,增强类
- 要用
抽象类接收动态代理对象
final Advice advice = new Advice();
final TargetInterfaceImpl targetInterface = new TargetInterfaceImpl();
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
//目标对象类加载器
targetInterface.getClass().getClassLoader(),
targetInterface.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
advice.before();
Object invoke = method.invoke(targetInterface, args);
advice.after();
return invoke;
}
}
);
proxy.save();
cglib实现动态代理
final Advice advice = new Advice();
final Target target = new Target();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Target.class);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
advice.before();
Object invoke = method.invoke(target, objects);
advice.after();
return invoke;
}
});
Target proxy = (Target) enhancer.create();
proxy.save();
基础用法
- applicationContext.xml配置,在aop的命名空间下
<bean id="target" class="com.java.proxy.aop.impl.TargetInterfaceImpl"></bean>
<bean id="myAspect" class="com.java.proxy.aop.MyAspect"></bean>
<aop:config>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut="execution(public void com.java.proxy.aop.impl.TargetInterfaceImpl.save())"/>
</aop:aspect>
</aop:config>
excution([修饰符] 返回值类型 包名.类名.方法名(参数类型))
访问修饰符可以省略
返回值、包名、类名、方法名可以使用星号* 通配符
包名与类名之间一个点.代表当前包下的类,两个点..表示当前包及其子包下的类
参数列表可以使用两个点..表示任意个数,任意类型的参数列表
常用 execution(* com.java.aop.*.*(..)) aop包下的任意类的任意方法、任意返回值、任意参数都可以作为切点
增强/通知类型

public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around - before - MyAspect");
Object proceed = pjp.proceed();
System.out.println("around - after - MyAspect");
return proceed;
}
<aop:around method="around" pointcut="execution(public void com.java.proxy.aop..*.*(..))"/>
<aop:before method="before" pointcut="execution(public void com.java.proxy.aop..*.*(..))"/>
<aop:after-returning method="after" pointcut="execution(public void com.java.proxy.aop..*.*(..))"/>
<aop:after-throwing method="afterThrowing" pointcut="execution(public void com.java.proxy.aop..*.*(..))"/>
<aop:after method="afterFinal" pointcut="execution(public void com.java.proxy.aop..*.*(..))"/>
<aop:pointcut id="myPoint" expression="execution(public void com.java.proxy.aop..*.*(..))"/>
<aop:around method="around" pointcut-ref="myPoint"/>
注解形式
<contex:component-scan base-package="com.java.proxy.aopanno"/>
<aop:aspectj-autoproxy/>
@Component("MyAspect")
@Aspect
public class MyAspect {
@Before("execution(* com.java.proxy.aopanno..*.*(..))")
public void before() {
System.out.println("before - MyAspect");
}
}
@Component("Target")
public class TargetInterfaceImpl implements TargetInterface {}
通知类型

切点表达式的抽取
@Pointcut("execution(* com.java.proxy.aopanno..*.*(..))")
public void pointcut() {
}
@After("MyAspect.pointcut()")
public void afterFinal() {
System.out.println("afterFinal");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around - before - MyAspect");
Object proceed = pjp.proceed();
System.out.println("around - after - MyAspect");
return proceed;
}
Spring-事务
- AOP思想
- 切点,业务方法;通知,事务方法
- 配置xml
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
//设置事务属性信息
<tx:attributes>
//被增强的方法
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.java.service.impl.*.*(..))"/>
</aop:config>
事务增强属性
<tx:method name="*" //被增强的方法名称
isolation="DEFAULT" //隔离级别
propagation="REQUIRED" //传播级别
timeout="1" //超时时间
read-only="false"/> //是否只读
基于注解
@Service("accountService")
@Transactional
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public void transfer(String outMan, String inMan, double balance) {
accountDao.out(outMan, balance);
int i = 1/ 0;
accountDao.in(inMan, balance);
}
}
@Bean("transactionManager")
public DataSourceTransactionManager getTransactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
<tx:annotation-driven transaction-manager="transactionManager"/>