(一)AOP使用示例
(1)XML配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean class="vi.com.bean.postprocessors.BeanFactoryPostProcessorA"></bean> <bean id="user" class="vi.com.bean.aotutag.User"></bean> <bean class="vi.com.bean.aspectj.MyAspectJ"></bean> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
(2)AspectJ
package vi.com.bean.aspectj; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; @Aspect public class MyAspectJ { // execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?) // 1.方法的可见性eg:public,private //2.返回值类型 //3.方法所在类的全路径名 //4.方法名类型 //5.方法的参数类型 //6.方法抛出的异常类型 @Pointcut("execution(* vi.com.bean.aotutag.User getId(..))") public void myPointCut(){ } @Before("execution(* *.getId(..))") public void before(){ System.out.println("before"); } @After("execution(* *.getId(..))") public void after(){ System.out.println("after"); } @Around("execution(* *.getId(..))") public void around(ProceedingJoinPoint p){ System.out.println("around1"); Object a = null; try { a = p.proceed(); }catch (Throwable e){ e.printStackTrace(); } System.out.println("around2"); } }
(3)拦截的bean
package vi.com.bean.aotutag; import java.util.List; import java.util.Map; import java.util.Set; public class User { private String id; public String getId() { return id; } public User setId(String id) { this.id = id; return this; } }
(4)测试类
import org.junit.Test; import org.springframework.context.ApplicationContext; import vi.com.bean.aotutag.User; import vi.com.bean.xmlclasspathappctx.MyClassPathXMLApplicationContext; public class AppTest { @Test public void test() { String path = "config.xml"; // BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(path)); ApplicationContext ctx = new MyClassPathXMLApplicationContext(path); User user = ctx.getBean(User.class); user.getId(); } }
(5)运行结果
around1
before
around2
after
(二)动态AOP自定义标签
(1)注册解析器
@Nullable public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { // 获取对应的命名空间 String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
public class AopNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } }
(2)解析
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 根据localname获取相应的解析器(在自定义的方法中注册的) BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); }
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null; }
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 注册或升级AspectJAnnotationAutoProxyCreator BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 获取proxy-target-class,expose-proxy属性 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); // 注册组件并通知,以便监听器做进一步处理 registerComponentIfNecessary(beanDefinition, parserContext); }
@Nullable private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); // 若已存在自动代理创建器且与当前不一致则根据优先级判别使用哪个 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); // 优先级判别 if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
- 属性处理proxy-target-class,expose-proxy
proxy-target-class:
若被代理bean实现了至少一个接口则会使用JDK动态代理,所有该bean实现的接口都将被代理
若被代理的bean没有实现任何一个接口则创建CGLIB代理
强制使用CGLIB代理:a:无法通知Finnal方法,因为他们不能被覆盖
b:需要将CGLIB二进制发行包放在classpath下面
expose-proxy:
目标对象内部的自我调用将无法实施切面中的增强
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) { if (sourceElement != null) { boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
(三)创建AOP代理
AbstractAutoProxyCreator.postProcessAfterInitialization
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 存在需要增强的方法 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理 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; }
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
来源:https://www.cnblogs.com/VVII/p/12180463.html