一、實例:
切點類:
package com.hxm.aop;
public class MathCalculator {
public int div(int i, int j){
System.out.println("執行除法");
return i/j;
}
}
切面類:
@Aspect
public class LogAspects {
//公共切點表達式
@Pointcut("execution(public int com.hxm.aop.MathCalculator.*(..))")
public void pointCut(){
}
//1、可以直接寫切點表達式
@Before("execution(public int com.hxm.aop.MathCalculator.*(..))")
public void logStart(){
System.out.println("除法運行,參數列表是:{}");
}
//2、也可以寫公共的切點函數,在本類中直接寫方法名
@After(value = "pointCut()")
public void logEnd(){
System.out.println("除法結束");
}
//3、外部類寫公共切點函數的全類名
@AfterReturning(value = "com.hxm.aop.LogAspects.pointCut()",returning = "result")
public void logReturn(Object result){
System.out.println("除法正常返回,運行結果:{"+result+"}");
}
@AfterThrowing(value = "pointCut()",throwing = "exception")
public void logException(Exception exception){
System.out.println("除法異常,異常信息:{}");
}
}
將切點類與切面類註冊到容器中:
@EnableAspectJAutoProxy
@Configuration
public class AopConfig {
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
二、源碼:
2.1 AOP功能的注入
起點:@EnableAspectJAutoProxy註解
@EnableAspectJAutoProxy
@Configuration
public class AopConfig {}
點進@EnableAspectJAutoProxy
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {}
發現用@Import導入了一個AspectJAutoProxyRegistrar。進入AspectJAutoProxyRegistrar,一路跟進下去,發現向容器中註冊了一個AnnotationAwareAspectJAutoProxyCreator,並命名爲internalAutoProxyCreator:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//註冊
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 注意在這個方法中已經把AnnotationAwareAspectJAutoProxyCreator的字節碼傳入方法了
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//註冊
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
AnnotationAwareAspectJAutoProxyCreator的繼承關係:
2.2 AnnotationAwareAspectJAutoProxyCreator後置處理功能
2.3 jdk & Cglib執行調用鏈
三、註解事務:
3.1 註解事務的注入
@EnableTransactionManagement
@Configuration
public class AopConfig {}
點進 @EnableTransactionManagement:
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
點進 @TransactionManagementConfigurationSelector,發現他繼承 ImportSelector,即通過組件的全限定類名向IOC容器註冊bean:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
//默認是這種方式
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
}
向容器中組冊了AutoProxyRegistrar和ProxyTransactionManagementConfiguration.
3.1.1 AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
實現了ImportBeanDefinitionRegistrar,即通過registry.registerBeanDefinition向容器中註冊組件。registerAutoProxyCreatorIfNecessary:
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
@Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
發現向容器中註冊了InfrastructureAdvisorAutoProxyCreator,他的繼承關係:
發現InfrastructureAdvisorAutoProxyCreator和之前的AnnotationAwareAspectJAutoProxyCreator異曲同工。
3.1.2 ProxyTransactionManagementConfiguration
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
發現向容器中註冊了3個bean:
1. BeanFactoryTransactionAttributeSourceAdvisor:
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
Advisor是增強器,通過pointcut(切入點)來增強方法,而pointcut又依賴TransactionAttributeSource。
2. TransactionAttributeSource:讀取/解析@Transactional註解
3. TransactionInterceptor:
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable
可以看出他是一個MethodInterceptor,即事務的功能主要是由它控制的。
3.2 註解事務的工作流程
首先創建一個事務demo:
@Service
public class DemoService {
@Transactional(rollbackFor = Exception.class)
public void test1() {
System.out.println("test1 run...");
int i = 1 / 1;
System.out.println("test1 finish...");
}
}
在調用方法時,由於不是接口,所以返回CglibAopProxy產生的代理類,並執行intercept方法:
class CglibAopProxy implements AopProxy, Serializable{
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// ......
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
// ......
}
}
此時,chain中有TransactionInterceptor:
進而執行TransactionInterceptor的invoke:
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//獲取事務管理器
final TransactionManager tm = determineTransactionManager(txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 創建事務
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
//執行方法調用
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
//事務回滾
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
//提交事務
commitTransactionAfterReturning(txInfo);
return retVal;
}
}
四、事務傳播行爲的原理
4.1 事務的幾種傳播行爲
4.2 傳播行爲原理
五、自定義AOP增強器
4.1以註解事務爲例,首先要明確幾個概念:
1. Advisor:增強器,如BeanFactoryTransactionAttributeSourceAdvisor,其繼承關係如下:
Advisor要依靠Pointcut來確定要增強的類和方法,以及依靠advice(即Interceptor,也叫攔截器)去執行真正的增強操作。
2. Pointcut:切點,如TransactionAttributeSourcePointcut,其繼承關係如下:
通過matches方法來確定要增強的類和方法。
3. Invocation:執行器如CglibMethodInvocation,其繼承關係如下:
當代理對象的invoke被執行時,所有的增強方法advice鏈chain和真正的調用方法method會被包裝成一個Invocation,並調用Invocation.proceed()。proceed會執行一下兩種流程:當chain中還有advice時,調用advice的invoke執行增強方法,並把自己傳入;當chain中無還未執行過的advice時,則反射調用method執行真正的方法。
4. advice:增強方法,如TransactionInterceptor,其繼承關係如下:
當advice的invoke被調用時,同時被傳入了Invocation,可以在調用Invocation.proceed進行後續攔截器鏈調用的前後以及拋出異常時,執行自己的增強方法。
4.2 實現自己的註解增強器
由此可見,要想實現一個自己的增強器,需要實現Advisor、Pointcut以及Interceptor。由於我們要實現一個自定義註解增強器,所以還需要實現一個註解解析器。
Advisor:
public class MyAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Autowired
private MyPointCut pointCut;
@Override
public Pointcut getPointcut() {
return pointCut;
}
}
PointCut:
public class MyPointCut extends StaticMethodMatcherPointcut {
/**
* 註解解析器
*/
@Autowired
MyAttributeSource attributeSource;
@Override
public boolean matches(Method method, Class<?> targetClass) {
return attributeSource.getAttribute(method,targetClass);
}
}
Interceptor:
public class MyInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("執行前");
try {
return invocation.proceed();
} finally {
System.out.println("執行後");
}
}
}
增強註解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAop {
}
註解解析器:
public class MyAttributeSource {
public boolean getAttribute(Method method, Class<?> targetClass){
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
specificMethod, MyAop.class, false, false);
if(attributes!=null){
return true;
}
return false;
}
}
config配置類:
@ComponentScan("com.hxm")
@Configuration
public class AopConfig {
/**
* 需要將攔截器注入
*/
@Bean
public MyAdvisor myAdvisor(){
MyAdvisor myAdvisor=new MyAdvisor();
myAdvisor.setAdvice(myInterceptor());
return myAdvisor;
}
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
@Bean
public MyAttributeSource myAttributeSource(){
return new MyAttributeSource();
}
@Bean
public MyPointCut myPointCut(){
return new MyPointCut();
}
}
測試類:
@Service
public class MyAopDemo {
@MyAop
public void test(){
System.out.println("im aop demo");
}
}
主類:
public class TxTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(AopConfig.class);
MyAopDemo demo=applicationContext.getBean(MyAopDemo.class);
demo.test();
}
}
結果:
執行前
im aop demo
執行後