文章目录
一、AOP的使用
1.1 基于XML
示例:
定义切面:
public class MyAspectXML {
public void before(){
System.out.println("MyAspectXML====前置通知");
}
public void afterReturn(Object returnVal){
System.out.println("后置通知-->返回值:"+returnVal);
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("MyAspectXML=====环绕通知前");
Object object= joinPoint.proceed();
System.out.println("MyAspectXML=====环绕通知后");
return object;
}
public void afterThrowing(Throwable throwable){
System.out.println("MyAspectXML======异常通知:"+ throwable.getMessage());
}
public void after(){
System.out.println("MyAspectXML=====最终通知..来了");
}
}
配置XML:
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--<context:component-scan base-package=""-->
<!-- 定义目标对象 -->
<bean name="productDao" class="com.zejian.spring.springAop.dao.daoimp.ProductDaoImpl" />
<!-- 定义切面 -->
<bean name="myAspectXML" class="com.zejian.spring.springAop.AspectJ.MyAspectXML" />
<!-- 配置AOP 切面 -->
<aop:config>
<!-- 定义切点函数 -->
<aop:pointcut id="pointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.add(..))" />
<!-- 定义其他切点函数 -->
<aop:pointcut id="delPointcut" expression="execution(* com.zejian.spring.springAop.dao.ProductDao.delete(..))" />
<!-- 定义通知 order 定义优先级,值越小优先级越大-->
<aop:aspect ref="myAspectXML" order="0">
<!-- 定义通知
method 指定通知方法名,必须与MyAspectXML中的相同
pointcut 指定切点函数
-->
<aop:before method="before" pointcut-ref="pointcut" />
<!-- 后置通知 returning="returnVal" 定义返回值 必须与类中声明的名称一样-->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut" returning="returnVal" />
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut" />
<!--异常通知 throwing="throwable" 指定异常通知错误信息变量,必须与类中声明的名称一样-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="throwable"/>
<!--
method : 通知的方法(最终通知)
pointcut-ref : 通知应用到的切点方法
-->
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
1.2 基于注解
示例:
切面类:
@Aspect
public class MyAspect {
/**
* 前置通知
*/
@Before("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
public void before(){
System.out.println("前置通知....");
}
/**
* 后置通知
* returnVal,切点方法执行后的返回值
*/
@AfterReturning(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))",returning = "returnVal")
public void AfterReturning(Object returnVal){
System.out.println("后置通知...."+returnVal);
}
/**
* 环绕通知
* @param joinPoint 可用于执行切点的类
* @return
* @throws Throwable
*/
@Around("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知前....");
Object obj= (Object) joinPoint.proceed();
System.out.println("环绕通知后....");
return obj;
}
/**
* 抛出通知
* @param e
*/
@AfterThrowing(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))",throwing = "e")
public void afterThrowable(Throwable e){
System.out.println("出现异常:msg="+e.getMessage());
}
/**
* 无论什么情况下都会执行的方法
*/
@After(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
public void after(){
System.out.println("最终通知....");
}
}
配置文件,开启自动配置:
<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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 启动@aspectj的自动代理支持-->
<aop:aspectj-autoproxy />
<!-- 定义目标对象 -->
<bean id="userDaos" class="com.zejian.spring.springAop.dao.daoimp.UserDaoImp" />
<!-- 定义aspect类 -->
<bean name="myAspectJ" class="com.zejian.spring.springAop.AspectJ.MyAspect"/>
</beans>
除了使用配置文件的<aop:aspectj-autoproxy />开启之外,也可以通过在配置类上增加@EnableAspectJAutoProxy注解即可。或者直接使用@Bean注解,在标注该注解的方法中,创建一个AnnotationAwareAspectJAutoProxyCreator的类实例。
二、@AspectJ形式的AOP实现原理
无论使用XML文件配置还是使用注解,自动织入AOP的实现都依赖于AnnotationAwareAspectJAutoProxyCreator类。该类实现了BeanPostProcessor接口,在类初始化完毕后会对每个Bean进行判断,并决定是否进行织入。如果需要织入,则使用JDK动态代理或者cglib动态代理生成对应的代理类,并替换原来的Bean。
而不管是在XML文件中配置<aop:aspectj-autoproxy />语句,还是在配置类上添加@EnableAspectJAutoProxy注解,其核心都是将AnnotationAwareAspectJAutoProxyCreator类添加到Spring容器中。
2.1 < aop:aspectj-autoproxy />
< aop:aspectj-autoproxy />语句的解析由AspectJAutoProxyBeanDefinitionParser类完成的,该类的主要作用就是在Spring容器中注册AnnotationAwareAspectJAutoProxyCreator类对应的BeanDefinition。
2.2 @EnableAspectJAutoProxy
该注解通过@Import注解,引入了AspectJAutoProxyRegistrar类。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 此处向容器注入了AnnotationAwareAspectJAutoProxyCreator类
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
该类的作用同样是向Spring容器中注册AnnotationAwareAspectJAutoProxyCreator
2.3 AnnotationAwareAspectJAutoProxyCreator的处理过程
该类的抽象父类AbstractAutoProxyCreator实现了BeanPostProcessor接口。核心逻辑都在抽象父类中,AnnotationAwareAspectJAutoProxyCreator的处理过程重写了父类的findCandidateAdvisors()方法,加入了对@Aspect注解锁标记的切面的扫描。
其父类实现的postProcessBeforeInstantiation在所有Bean实例化之前,就将所有的Advise切面类都加载完成,并放到一个容器AdviseBeans中。
其父类实现的postProcessAfterInitialization方法则在所有Bean实例化之后,对所有Bean进行判断是否需要增强,如果需要则从Advise容器中找出匹配的切面,然后使用动态代理进行增强。
AbstractAutoProxyCreator源码:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//shouldSkip方法调用findCandidateAdvisors()方法加载切面
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 will 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());
return proxy;
}
}
return null;
}
// 生成代理对象
@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;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && 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.
// 获取切面Advisor
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 Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 解析目标对象接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 生成Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 生成代理
return proxyFactory.getProxy(getProxyClassLoader());
}
}
AnnotationAwareAspectJAutoProxyCreator源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.aop.aspectj.annotation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.Assert;
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
private List<Pattern> includePatterns;
private AspectJAdvisorFactory aspectJAdvisorFactory;
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
public AnnotationAwareAspectJAutoProxyCreator() {
}
//....其他代码
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder = new AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
//重写了加载切面的方式,加载@Aspect注解所代表的切面
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
protected boolean isInfrastructureClass(Class<?> beanClass) {
return super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass);
}
protected boolean isEligibleAspectBean(String beanName) {
if (this.includePatterns == null) {
return true;
} else {
Iterator var2 = this.includePatterns.iterator();
Pattern pattern;
do {
if (!var2.hasNext()) {
return false;
}
pattern = (Pattern)var2.next();
} while(!pattern.matcher(beanName).matches());
return true;
}
}
private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {
public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
super(beanFactory, advisorFactory);
}
protected boolean isEligibleBean(String beanName) {
return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
}
}
}
3. 其他形式
参考:
https://blog.csdn.net/xiaoshuai1127/article/details/76221401
https://www.cnblogs.com/z00377750/p/11793088.html