Today try to use Spring + ASPECTJ's AOP, encounter some problems, there is no way to intercept the bean, such as controller inside the method. Online search for a large pile of things, there is no use, and see Spring official website reference also did not see what the problem. In this case, we have to look at the source code analysis, first we use the way of annotations:
The Beans.xml configuration file for spring is as follows:
<?XML version= "1.0" encoding= "UTF-8"?><Beansxmlns= "Http://www.springframework.org/schema/beans"Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"Xmlns:context= "Http://www.springframework.org/schema/context"Xmlns:mvc= "Http://www.springframework.org/schema/mvc"XMLNS:AOP= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP"xsi:schemalocation= "Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ Spring-beans-4.2.xsd Http://www.springframework.org/schema/context Http://www.springframework.org/schema/context /spring-context.xsd Http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/ Spring-mvc.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www.springframework.org/schema/aop/ Spring-aop.xsd " > <Context:component-scanBase-package= "Org.mosmith.togethertravel" /> .... <Aop:aspectj-autoproxy/></Beans>
In fact, the above <aop:aspectj-autoroxy/> corresponds to the annotation @enableaspectjautoproxy. As you can see from the definition below enableaspectjautoproxy, annotations are imported into the Aspectjautoproxyregistrar configuration class.
@Target (Elementtype.type) @Retention (retentionpolicy.runtime) @Documented @import (Aspectjautoproxyregistrar. class ) public @Interface enableaspectjautoproxy { /** * Indicate whether subclass-based (CGLIB) proxies is to being created as opposed * to standard Java interface-based Proxi Es. The default is {@code false}. */ Boolean default false ;}
Aspectjautoproxyregistrar mainly in the beandefinitionregistry inside registered Annotationawareaspectjautoproxycreator. From the Annotationawareaspectjautoproxycreator inheritance structure can be seen Annotationawareaspectjautoproxycreator is a beanpostprocessor, Similar to ENABLEWEBMVC, this class is used to integrate ASPECTJ and spring's IOC containers.
We jump to the related method of ASPECTJ-related annotation processing on the inheritance structure, which overrides the findcandidateadvisors of the parent class (the parent class primarily handles the XML-mode configuration of the advisor, This adds a adivisor scan of the annotation declaration, and we jump to the buildaspectjadvisors method inside the Beanfactoryaspectjadvisorsbuilder , From this method we can see that it takes all the beans from beanfactory, which is our context, and then checks if the bean has @aspect annotations, and if so, constructs the advisor metadata, which does not directly build the advisor instance. Because it is managed by the spring IOC container.
Public classAnnotationawareaspectjautoproxycreatorextendsaspectjawareadvisorautoproxycreator {... @OverrideprotectedList<advisor>findcandidateadvisors () {//ADD all the Spring advisors found according to superclass rules.list<advisor> Advisors =Super. Findcandidateadvisors (); //Build Advisors for all AspectJ aspects in The Bean factory.Advisors.addall ( This. Aspectjadvisorsbuilder.buildaspectjadvisors ()); returnAdvisors; } ...}
/*** Helper for retrieving @AspectJ beans from a beanfactory and building * Spring Advisors based on them Auto-proxying. * * @authorJuergen Hoeller *@since2.0.2 *@seeAnnotationawareaspectjautoproxycreator*/ Public classbeanfactoryaspectjadvisorsbuilder {..../*** Look for aspectj-annotated aspect beans in the current bean factory, * and return to a list of Spring AOP a Dvisors representing them. * <p>creates a Spring Advisor for each AspectJ advice method. * @returnThe list of {@linkorg.springframework.aop.Advisor} Beans *@see#isEligibleBean*/ PublicList<advisor>buildaspectjadvisors () {List<String> Aspectnames =NULL; synchronized( This) {Aspectnames= This. Aspectbeannames; if(Aspectnames = =NULL) {List<Advisor> Advisors =NewLinkedlist<advisor>(); Aspectnames=NewLinkedlist<string>(); String[] Beannames=Beanfactoryutils.beannamesfortypeincludingancestors ( This. Beanfactory, Object.class,true,false); for(String beanname:beannames) {if(!Iseligiblebean (Beanname)) { Continue; } //We must is careful not to instantiate beans eagerly as in this//Case They would is cached by the Spring container and would not//Have been weavedClass<?> Beantype = This. Beanfactory.gettype (Beanname); if(Beantype = =NULL) { Continue; } if( This. Advisorfactory.isaspect (Beantype)) {Aspectnames.add (beanname); Aspectmetadata AMD=NewAspectmetadata (Beantype, beanname); if(Amd.getajtype (). Getperclause (). Getkind () = =Perclausekind.singleton) {metadataawareaspectinstancefactory Factory=NewBeanfactoryaspectinstancefactory ( This. Beanfactory, Beanname); List<Advisor> classadvisors = This. Advisorfactory.getadvisors (Factory); if( This. Beanfactory.issingleton (Beanname)) { This. Advisorscache.put (Beanname, classadvisors); } Else { This. Aspectfactorycache.put (Beanname, Factory); } advisors.addall (Classadvisors); } Else { //per target or per this. if( This. Beanfactory.issingleton (Beanname)) { Throw NewIllegalArgumentException ("Bean with Name '" + Beanname + "are a singleton, but ASP ECT instantiation model is not singleton "); } metadataawareaspectinstancefactory Factory=NewPrototypeaspectinstancefactory ( This. Beanfactory, Beanname); This. Aspectfactorycache.put (Beanname, Factory); Advisors.addall ( This. Advisorfactory.getadvisors (Factory)); } } } This. Aspectbeannames =Aspectnames; returnAdvisors; } } if(Aspectnames.isempty ()) {returncollections.emptylist (); } List<Advisor> Advisors =NewLinkedlist<advisor>(); for(String aspectname:aspectnames) {List<Advisor> cachedadvisors = This. Advisorscache.get (Aspectname); if(Cachedadvisors! =NULL) {advisors.addall (cachedadvisors); } Else{metadataawareaspectinstancefactory Factory= This. Aspectfactorycache.get (Aspectname); Advisors.addall ( This. Advisorfactory.getadvisors (Factory)); } } returnAdvisors; } ....}
Let's take a look at the bean. When instantiated, Spring takes the Getadvicesandadvisorsforbean method to remove the advisor bean that intercepts the bean, creates the proxy, and then returns the proxy. This way, you can intercept the bean's method call. But by debugging, it's not the place where ASPECTJ to intercept, ASPECTJ implements the Intercept in the Abstractautoproxycreator.postprocessafterinitialization method, which calls the Wrapifnecessary method to wrap,wrapper The Bean class is to take advantage of the Cgli b dynamically generated subclasses.
@SuppressWarnings ("Serial") Public Abstract classAbstractautoproxycreatorextendsProxyprocessorsupportImplementssmartinstantiationawarebeanpostprocessor, Beanfactoryaware {..... @Override PublicObject postprocessbeforeinstantiation (class<?> beanclass, String beanname)throwsbeansexception {Object CacheKey=Getcachekey (Beanclass, beanname); if(Beanname = =NULL|| ! This. Targetsourcedbeans.contains (Beanname)) { if( This. Advisedbeans.containskey (CacheKey)) { return NULL; } if(Isinfrastructureclass (beanclass) | |Shouldskip (Beanclass, Beanname)) { This. Advisedbeans.put (CacheKey, Boolean.false); return NULL; } } //Create Proxy Here if we have a custom targetsource. //suppresses unnecessary default instantiation of the target bean://The Targetsource would handle target instances in a custom fashion. if(Beanname! =NULL) {Targetsource Targetsource=Getcustomtargetsource (Beanclass, beanname); if(Targetsource! =NULL) { This. Targetsourcedbeans.add (Beanname); Object[] Specificinterceptors=Getadvicesandadvisorsforbean (Beanclass, Beanname, Targetsource); Object Proxy=Createproxy (Beanclass, Beanname, Specificinterceptors, Targetsource); This. Proxytypes.put (CacheKey, Proxy.getclass ()); returnproxy; } } return NULL; } ....
/**
* Create a proxy with the configured interceptors if the beans is
* Identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public object Postprocessafterinitialization (object bean, String beanname) throws Beansexception {
if (bean! = null) {
Object CacheKey = Getcachekey (Bean.getclass (), beanname);
if (!this.earlyproxyreferences.contains (CacheKey)) {
Return Wrapifnecessary (Bean, beanname, CacheKey);
}
}
return bean;
}
....}
The principle of Spring integrated ASPECTJ