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