This is the 21st day of my participation in the August Text Challenge.More challenges in August

preface

I’ll start by asking a question about whether Spring AOP works. The pseudocode is as follows

/ / parent class
class P {
  
  public void pr(a){
    print('is pr')}}/ / subclass
@compont
class S{}@compont
class D{
  @Autowired
  S s;
  
  void ss(a){
    s.pr()
  }
}

Copy the code

How can you cut to the PR () method?

Some of my friends here would say let’s just cut through all the methods of the parent class

That can be done, but it’s not good

Because I just want to cut all the methods of class S, including its parent, and even its parent

Code thinking

Originally I also gave up, these two days in the process of learning transaction annotation source code I found a new idea

Transaction annotation parsing chapter I have said more clearly, here do not repeat, say the main point

BeanFactoryTransactionAttributeSourceAdvisor inherited AbstractPointcutAdvisor plane logic into the spring

TransactionAttributeSourcePointcut the most main is to judge the bean in a method is called when the edge is in line with the

The TransactionInterceptor is the main running logic for the aspect

So how BeanFactoryTransactionAttributeSourceAdvisor into spring, before the article didn’t speak, I add here

We from org. Springframework. Aop. Framework. Autoproxy. AbstractAdvisorAutoProxyCreator# findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class
        beanClass, String beanName) {
  // All section enhancers
  / / end call BeanFactoryAdvisorRetrievalHelper# findAdvisorBeans
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
  // All qualified enhancers
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  / / extension
		extendAdvisors(eligibleAdvisors);
		if(! eligibleAdvisors.isEmpty()) {/ / sorting
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
Copy the code
public List<Advisor> findAdvisorBeans(a) {
		// Cache data
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// Find all classes implementing Advisor from the current container
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true.false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}

		List<Advisor> advisors = new ArrayList<>();
		for (String name : advisorNames) {
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					....
				}
				else {
					try {
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch(BeanCreationException ex) { ..... }}}}return advisors;
	}
Copy the code

So at this point in how BeanFactoryTransactionAttributeSourceAdvisor definitions, but eventually are Advisor interface is realized

And much AbstractBeanFactoryPointcutAdvisor the implementation method, we only need to integrate this abstract class

Code implementation

Section judgment

@Slf4j
public class DbSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	@Override
	public boolean matches(Method method, @NullableClass<? > targetClass) {
		if (targetClass == null) {
			return false; } Class<? > declaringClass = method.getDeclaringClass(); String superClassName = declaringClass.getName();if(! targetClass.getName().equals("com.impl.S")) {// Methods of class S do not cut
      return false;
    }
			

		return superClassName.equals("com.impl.S")  || superClassName.equals("com.impl.P"); }}Copy the code

The interceptor

/** ** system database operation processing section */
@Slf4j
public class SysDbInterceptor implements MethodInterceptor.Serializable {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

      // Enhance processing
        Object proceed;
        try {
            proceed = invocation.proceed();
        } finally{... }returnproceed; }}Copy the code

Injection spiring

@Component
public class DbPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor {
 
    DbSourcePointcut pointcut = new DbSourcePointcut();

    public DbPointcutAdvisor(a) {
        setAdvice(new SysDbInterceptor());
    }

    public void setClassFilter(ClassFilter classFilter) {
        this.pointcut.setClassFilter(classFilter);
    }


    @Override
    public Pointcut getPointcut(a) {
        returnpointcut; }}Copy the code