preface
The last article covered how Spring gets the corresponding Bean enhancement, and this time I’ll focus on how Spring creates a Spring proxy once it gets the enhancement.
Before we get down to business, let me give you a rough flow chart of Spring’s proxy creation
So let’s go back toAbstractAutoProxyCreator.class
In the classwrapIfNecessary
Methods.
- See the source code (
AbstractAutoProxyCreator.class
)
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {/ / if already processed the if (StringUtils. HasLength (beanName) && enclosing targetSourcedBeans. The contains (beanName)) { return bean; } // No need to enhance if (boolea.false. Equals (this.AdvisedBeans.get (cacheKey))) {return bean; } // Whether the given bean class is an infrastructure class, infrastructure classes should not be proxied, Or configuration specified beans do not need agent if (isInfrastructureClass (bean. GetClass () | | shouldSkip (bean. GetClass (), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Get all advisors that can be applied to the current Bean (sorted according to @order) // Create proxy if we have advice. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // If you have an Advisor, do the following dynamic proxy creation process if (specificInterceptors! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, boolea.true); Object Proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // Save the Class object of the proxy object (a subclass of the target Class) this.proxytypes.put (cacheKey, proxy.getClass()); // Return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }Copy the code
In the previous Spring source of creating the enhancer of AOP agent acquisition of articles, mainly around the getAdvicesAndAdvisorsForBean method, main is to get all the corresponding Bean enhancer, and get to the target Bean the matched Advisor,
Next, we’ll examine the next method, createProxy,
- See the source code (
AbstractAutoProxyCreator.class
)
protected Object createProxy(Class<? > beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } // create a ProxyFactory ProxyFactory ProxyFactory = new ProxyFactory(); // Copy some properties of the current ProxyConfig (e.g. ProxyTargetClass, exposeProxy) proxyFactory.copyfrom (this); / / judge whether the proxy class (that is, whether to open the additional agents) default is false if (proxyFactory. IsProxyTargetClass ()) {/ / Explicit handling of JDK proxy the targets (for introduction advice scenarios) if (Proxy.isProxyClass(beanClass)) { // Must allow for introductions; can't just set interfaces to the proxy's interfaces only. for (Class<? > ifc : beanClass.getInterfaces()) { proxyFactory.addInterface(ifc); }}} else {// If this Bean is configured for class proxy, // No proxyTargetClass Flag 残 权, let's apply our default checks... if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else {// Check whether the interface implemented by the current Bean contains a proxiable interface, if not, EvaluateProxyInterfaces (beanClass, proxyFactory) need to be promoted by CGLIB. }} // Further processing of the input advisors, since there may also be Advice types that need to be wrapped as DefaultPointcutAdvisor // If the 'interceptorNames' interceptor is configured, Advisor[] Advisors = buildAdvisors(beanName, specificInterceptors); // Add Advisor array proxyFactory.addAdvisors(advisors); / / agent factory set TargetSource proxyFactory object. SetTargetSource (TargetSource); CustomizeProxyFactory (ProxyFactory); customizeProxyFactory(ProxyFactory); // used to control whether notification changes are allowed after the agent factory has been configured. (Default false) (that is, it is not allowed to change the configuration of the proxy after it has been configured). proxyFactory.setFrozen(this.freezeProxy); If (advisorsPreFiltered()) {// Set 'preFiltered' to 'true' // so Advisor Are not based on ClassFilter filtering, and directly through the processing method were intercepted MethodMatcher determine whether proxyFactory. SetPreFiltered (true); } // If the bean class is not loaded locally in the override classloader, // Use original ClassLoader if bean class not locally loaded in overriding class loader ClassLoader classLoader = getProxyClassLoader(); if (classLoader instanceof SmartClassLoader && classLoader ! = beanClass.getClassLoader()) { classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader(); } return proxyfactory.getProxy (classLoader); }Copy the code
-
Source code analysis
ProxyFactory = new ProxyFactory(); Create a new factory class and, looking back, it’s obvious that Spring delegates the creation of the proxy class to ProxyFactory.
Proxyfactory.getproxy (classLoader); This method creates a proxy object.
-
Look at the source code (Proxyfactory. Java)
Public Object getProxy(@nullable ClassLoader ClassLoader) {// Create an AOP proxy class (JdkDynamicAopProxy or ObjenesisCglibAopProxy is implemented by creating a proxy object for the target Bean according to the AOP proxy in DefaultAopProxyFactory. CreateAopProxy ().getProxy(classLoader); }Copy the code
-
Source code analysis
From the above comments, you can feel that we are finally coming to the topic of deciding which proxy method to use. First we see the createAopProxy method in the getProxy method. Its default implementation is in the DefaultAopProxyFactory class. It passes through the createAopProxy method of the ProxyCreatorSupport class.
-
Look at the source code (ProxyCreatorSupport. Java)
protected final synchronized AopProxy createAopProxy() { if (! this.active) { activate(); } // Get the AOP proxy factory, default is DefaultAopProxyFactory, Only this implementation // then uses it to create an AOP proxy (JdkDynamicAopProxy or ObjenesisCglibAopProxy) return based on creating the current AdvisedSupport configuration manager getAopProxyFactory().createAopProxy(this); }Copy the code
Next we go directly to the implementation class DefaultAopProxyFactory that implements the createAopProxy method.
- See the source code (
DefaultAopProxyFactory.java
)
@override public AopProxy createAopProxy(AdvisedSupport Config) throws AopConfigException {// Checks whether /* * meets the following conditions Config.isoptimize () requires optimization, which defaults to 'false' to control whether agents created with CGLIB use aggressive optimization strategies * Unless you fully understand how AOP agents handle optimization, Otherwise don't recommend users to use this setting, currently this property is used only for additional agents, for the JDK dynamic proxy agent (default) void * config. IsProxyTargetClass () using class agent, CGLIB dynamic proxy is set to 'false' by default: < aop: aspectj - autoproxy proxy - target - class = "true" / > * hasNoUserSuppliedProxyInterfaces (config) / / if there is a proxy interface * / if (! NativeDetector.inNativeImage() && (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) { Class<? > targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // If the target class is an interface or a subclass of java.lang.reflect.Proxy then use the JDK dynamic Proxy again, create a JdkDynamicAopProxy object, and pass in the AdvisedSupport configuration manager, And return the if (targetClass isInterface () | | Proxy. IsProxyClass (targetClass)) {return new JdkDynamicAopProxy (config); } // Create an ObjenesisCglibAopProxy object, pass in the AdvisedSupport configuration manager, and return new ObjenesisCglibAopProxy(config); } else {// Create a JdkDynamicAopProxy object, pass in the AdvisedSupport configuration manager, and return new JdkDynamicAopProxy(config); }}Copy the code
-
Source code analysis
In this DefaultAopProxyFactory class can see obviously that here according to Optimize, ProxyTargetClass, hasNoUserSuppliedProxyInterfaces determination of three attributes, see whether to use which dynamic proxy.
Optimize specifies whether agents created with CGLIB use aggressive optimization strategies. This setting is not recommended unless you fully understand how AOP proxies handle optimizations. Currently, this property only works for CGLIB proxies and does not work for JDK dynamic proxies (default proxies)
ProxyTargetClass uses class proxies, that is, CGLIB dynamic proxies default to false
<aop:aspectj-autoproxy proxy-target-class=”true”/>
HasNoUserSuppliedProxyInterfaces (config) / / if there is a proxy interface
JDK and Cglib instructions
- If the target object implements an interface, the JDK’s dynamic proxy implementation of AOP is used by default
- You can force CGLIB to implement AOP if the target object implements an interface.
- If the target object does not implement an interface and must use the CGLIB library, Spring automatically converts between JDK dynamic proxies and CGLIB
How do I enforce AOP with CGLIB?
- Add the CGLIB library, Spring_HOME/ CGLIB /*.jar
- Add < AOP :aspectj-autoproxy proxy-target-class=”true”/> to the Spring configuration file.
What is the difference between JDK dynamic proxy and CGLIB bytecode generation?
- JDK dynamic proxies can only generate proxies for classes that implement the interface, not for classes.
- GLIB implements proxying for classes, essentially generating a subclass of the specified class that overrides its methods. Because it is inherited, it is best not to declare the class or method final.
That concludes how Spring decides which dynamic proxy approach to use.
For more exciting content, please search on wechat [code to meet you]