This is the third day of my participation in the August More text Challenge. For details, see:August is more challenging

An overview of the

Have used the Spring framework partners all know, the importance of SPRING AOP, learning source code is essential, the text record some source tracking source skills learning experience, the need to correct and correct the error please leave a comment below

A general analysis of AOP principle

This Internet search a lot of, repeat to elaborate without meaning, say next my personal understanding, key two words agent what call agent, and the bank is the same, you do what should pass somebody else’s hand, so as long as your money has changed the bank all know

Same thing with Spring. Let’s say I have a class

public class A{
	void test(a){
		system.out.println("test run"); }}Copy the code

We need to make an aspect of test() in A and spring will generate A proxy object that you actually call, so you’ll have an aspect when you call the method

class ProxyThe $1{ A a; test(){ a.test(); }}Copy the code

This can also be viewed as a static proxy. If you have multiple proxies, you might see something like thisBut this code is not dead, so the proxy cannot be static, also known as dynamic proxy

There are two ways to dynamically generate proxy classes in Spring

  • cglib
  • The JDK agent

How to use them in detail is not explained in this article

To prepare the demo

The first is a Spring portal

@ComponentScan("bean")
@EnableAspectJAutoProxy
public class Application {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = newAnnotationConfigApplicationContext(Application.class); ComService bean = context.getBean(ComService.class); bean.testAop(); }}Copy the code

A proxied object

@Service
public class ComService {


	public void testAop(a){
		System.out.println("===== ComService ===="); }}Copy the code

Section definition

@Aspect
@Component
public class Aop {
	@Pointcut("execution(public * bean.service.ComService.testAop())")
	public void businessService(a) {}

	@Around("businessService()")
	public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
		// start stopwatch
		Object retVal = pjp.proceed();
		System.out.println(pjp.getSignature().getName() + "=== section");
		// stop stopwatch
		returnretVal; }}Copy the code

Source code analysis

In fact, online such source code parsing posts many, but have in common, are directly tell you where to look at this code, and then paste some of their understanding comments, but as a new learning spring or spring source research is not deep development partners, I want to know how you find this code, This article shares where I found the key source code step by step. The technique may be very low, but it is quite practical. This is how I find most framework source code if I don’t read the blog first

Here are two main answers

When is the section resolved

In a project we represent aspects by adding annotations to the classes@AspectSo there must be some code that’s the easiest way to parse this annotation and just see where it’s called, so I just downloaded the spring source code, and that’s itYou can seeorg.aspectj.internal.lang.reflect.AjTypeImpl#getPerClauseWe have get and we’re looking at where is this method being calledAt this point, you can interrupt in some way you think is possible and see if it comes in (it’s low but I think it’s useful for a guy like me).

// The code is abbreviated
List<String> aspectNames = this.aspectBeanNames;
// This method is called more than once
if (aspectNames == null) {
  List<Advisor> advisors = new ArrayList<>();
  aspectNames = new ArrayList<>();
  String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    this.beanFactory, Object.class, true.false);
  for (String beanName : beanNames) {
    ....
    // Check whether there are aspect annotations
    // This is not the class that calls the method, so finding this code is a fluke
    if (this.advisorFactory.isAspect(beanType)) {
      aspectNames.add(beanName);
      AspectMetadata amd = new AspectMetadata(beanType, beanName);
      // This will call the method I guessed earlier
      / / the method will be called a below advisors. The addAll (this) advisorFactory) getAdvisors (factory));
      if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
       ...
      }
      else{... }}}this.aspectBeanNames = aspectNames;
  return advisors;
}
		
Copy the code

How to generate proxy classes

Here to find the source code some clever, a few days ago just learned the source code of the Spring bean lifecycle, so directly inDefaultSingletonBeanRegistry#getSingleton()Debug, write a breakpoint conditionAnd then a little bit of release code, look at the return value obj and if it’s changed then it’s foundorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBeanIn this method, the object has been initially created

You can seeAbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitializationAfter this line of code this object is no longer the same object as it was before and then we start to analyze it

Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
	Object current = processor.postProcessAfterInitialization(result, beanName);
	if (current == null) {
		return result;
	}
	result = current;
}
Copy the code

Similarly is also break point Can find AbstractAutoProxyCreator# postProcessAfterInitialization – > AbstractAutoProxyCreator# wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {...// Create an aspect proxy
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// Generate the proxy class
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}
	
	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}
Copy the code

So let’s go down proxyFactor #getProxy

	// createAopProxy() this method returns an object that implements AopProxy
	return createAopProxy().getProxy(classLoader);
Copy the code

Defaultaopproxyfactor #createAopProxy This determines how the proxy class is generated

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  if(! IN_NATIVE_IMAGE &&// Whether to optimize
      (config.isOptimize() || 
       // Whether direct proxy and interface
       config.isProxyTargetClass() ||
       / / judge whether realized org. Springframework. Aop. SpringProxy interface classes
       hasNoUserSuppliedProxyInterfaces(config))) {
    // Class that needs to be proxiedClass<? > targetClass = config.getTargetClass();if (targetClass == null) {
      throw new AopConfigException();
    }
    // If it is an interface
    if (targetClass.isInterface() 
        // Is itself a proxy class
        || Proxy.isProxyClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    return newJdkDynamicAopProxy(config); }}Copy the code

Simply put, if the class being proxied is an interface, or is itself a proxy class then use JDK proxy, otherwise it’s a Cglib proxy because the JDK can only proxy interfaces

So either the JDK proxy or the Cglib proxy, the purpose is to generate the layer proxy class and then I want to know what to do if I have multiple sections,

org.springframework.aop.framework.JdkDynamicAopProxy#invoke

org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader) Debug the above code to see what methods a bean has in its facets

feeling

With this aop general flow in mind, we can have a general idea of the problems we encounter in development. For example, common AOP failure problems can be summarized in two aspects

  • The aspect is not resolved to
  • The proxy class is not generated

Most problems can be solved by debugging, if you know where to debug

The last

Welcome to comment below your source reading skills, I also want to learn