Spring基础AOP面向切面编程
Posted 烟锁迷城
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring基础AOP面向切面编程相关的知识,希望对你有一定的参考价值。
1、代理模式
代理模式是二十三种设计模式中较为重要的一种,作用是增强被代理对象的功能,保护被代理对象。代理模式分为静态代理与动态代理两种。
1.1、静态代理
静态代理非常简单,就是通过代理固定的类来增强方法。
public interface Course {
void giveAClass();
}
public class Math implements Course {
@Override
public void giveAClass() {
System.out.println("学习数学");
}
}
public class MathTeacher implements Course {
private Course course;
public MathTeacher(Course course){
this.course = course;
}
@Override
public void giveAClass() {
System.out.println("开始上课");
this.course.giveAClass();
System.out.println("下课");
}
}
public class Student {
public static void main(String[] args) {
Course course = new MathTeacher(new Math());
course.giveAClass();
}
}
1.2、动态代理
动态代理可以分为两类,JDK动态代理和CGLib动态代理。
1.2.1、JDK动态代理
JDK动态代理的目标对象实现一个接口,就可以被代理。
public class JDKSchool implements InvocationHandler{
private Object target;
public Object getInstance(Object obj) throws Exception{
this.target = obj;
Class<?> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj = method.invoke(this.target,args);
after();
return obj;
}
private void before(){
System.out.println("开始上课");
}
private void after(){
System.out.println("下课");
}
}
public class Test {
public static void main(String[] args) {
try {
Course course = (Course) new JDKSchool().getInstance(new Math());
course.giveAClass();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.2.2、CGLib动态代理
CGLib动态代理的目标无需实现接口,CGLib会生成一个类,继承目标类进行代理。
public class CGLibSchool implements MethodInterceptor {
public Object getInstance(Class<?> clazz){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object obj = methodProxy.invokeSuper(o,objects);
after();
return obj;
}
private void before(){
System.out.println("开始上课");
}
private void after(){
System.out.println("下课");
}
}
public class Sports {
public void open(){
System.out.println("开始运动会");
}
}
try {
Sports sports = (Sports) new CGLibSchool().getInstance(Sports.class);
sports.open();
} catch (Exception e) {
e.printStackTrace();
}
2、AOP介绍
AOP为面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP的功能将切面切入到主业务逻辑中,所谓交叉业务逻辑是指通用的,与主业务逻辑无关的代码,如安全检查,事务,日志等,若不使用AOP,则会出现代码纠缠,即交叉业务逻辑与主业务逻辑混合在一起,这样会使主业务逻辑变得混杂。
2.1、AspectJ
2.1.1、jar包引入
需要引入jar包才能使用AspectJ
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
</dependencies>
2.1.2、放开AspectJ
@EnableAspectJAutoProxy注解可以将AspectJ的使用放开。
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.lichong.service")
public class JavaConfig {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
IUserService bean = applicationContext.getBean(IUserService.class);
bean.fun1();
}
}
2.1.3、创建切面类
切面类中的切面方法有几种不同的通知类型,具体注解及解释如下:
通知类型 | 说明 | 使用注解 |
前置通知 | 目标方法执行之前调用 | @Before |
后置通知 | 目标方法执行完成之后调用 | @AfterReturning |
环绕通知 | 目标方法执行前后都会调用方法,且能增强结果 | @Around |
异常处理通知 | 目标方法出现异常调用 | @AfterThrowing |
最终通知 | 无论程序执行是否正常,该通知都会执行,类似于try catch finally中的finally代码块 | @After |
2.1.4、创切面表达式
切面表达式是切面注解所使用的的表达式内容,具体注解及解释如下:
表达式类型 | 说明 |
execution | 定位到目标对象的方法上 |
within | 定位到具体的类型上 |
this | 代理对象的类型 |
target | 目标对象的类型 |
args | 参数的类型 |
@args | 传入的参数被注解修饰 |
@within | 类型修饰的注释 |
@annotation | 方法休息的注释 |
- *:表达式用法为0到多个匹配
- ..:表达式用法为方法参数中表示任意个参数,用于包名后表示当前包及其子包
- +:表达式用法为用在类型后表示当前类及其子类
- &&:表达式用法为用在两个表达式之间,作为与条件
- execution:表达式语法为execution([访问权限类型] 返回值类型 [全限定类名] 方法名(参数类型)[抛出的异常类型]),中括号内的内容是可选内容。
- within:表达式语法为within(全限定类名),将指定类的全部方法作为切点
- this:表达式语法为this(全限定类名),在AOP中,如果目标对象有实现接口,默认使用JDK代理模式,因此无法找到代理的类,若想使用,必须在增加@EnableAspectJAutoProxy(proxyTargetClass = true),这样就将代理模式由JDK改为CGLib,this才能正常使用
- target:表达式语法为target(全限定类名),将指定类的全部方法作为切点
- args:表达式语法为args(参数类型),将指定参数类型作为切点
- @args:表达式语法为@args(注解),将被指定注解修饰的类作为参数的方法作为切点
- @within:表达式语法为@within(注解),将被指定注解修饰的类的全部方法作为切点
- @annotation:表达式语法为@annotation(注解),将被指定注解修饰的类的方法作为切点
2.1.5、代码示例
具体使用方法如下,execution内表达式的意思是任何返回值类型,在com.lichong.service.impl包下的所有类的所有方法,参数类型是任意类型的都会被切面。
@Pointcut注解用来提取表达式,增强代码复用
@Aspect
@Component
public class UserAspectJ1 {
@Pointcut("execution(* com.lichong.service.impl.*.*(..))")
public void point1() {
}
@Before("point1()")
public void aspectMethod1() {
System.out.println("before");
}
@Before("within(com.lichong.service.impl.UserServiceImpl)")
public void aspectMethod2() {
System.out.println("before2");
}
@Before("this(com.lichong.service.impl.UserServiceImpl)")
public void aspectMethod3() {
System.out.println("before3");
}
@Before("target(com.lichong.service.impl.UserServiceImpl)")
public void aspectMethod4() {
System.out.println("before4");
}
@Before("args(String)")
public void aspectMethod5() {
System.out.println("before5");
}
@Before("@args(com.lichong.aspect.AopAnnotation01)")
public void aspectMethod6() {
System.out.println("before6");
}
@Before("@within(com.lichong.aspect.AopAnnotation03)")
public void aspectMethod7() {
System.out.println("before7");
}
@Before("@annotation(com.lichong.aspect.AopAnnotation02)")
public void aspectMethod8() {
System.out.println("before8");
}
@Before("@annotation(AopAnnotation02)")
public void aspectMethod9(AopAnnotation02 aopAnnotation02) {
String value = aopAnnotation02.value();
System.out.println("before9" + value);
}
}
注解1,用于参数类,注意,此处并非是应用范围为参数,而是放在作为参数的类上,所以@Target注解的使用范围为TYPE(类)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AopAnnotation01 {
}
注解2,用于方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AopAnnotation02 {
String value() default "";
}
注解3,用于类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AopAnnotation03 {
}
构建参数
@AopAnnotation01
public class Param {
}
构建接口
public interface IUserService {
void fun1();
String fun2();
String fun3(String name);
String fun4(Param param);
}
实现方法
@Service
@AopAnnotation03
public class UserServiceImpl implements IUserService {
@AopAnnotation02
public void fun1() {
System.out.println("fun1");
}
@AopAnnotation02("aopxxx")
public String fun2() {
System.out.println("fun2");
return "fun2";
}
public String fun3(String name) {
System.out.println("fun3");
return "fun3 "+name;
}
public String fun4(Param param) {
System.out.println("fun4");
return "fun4";
}
}
开启CGLib代理,开始测试
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan({"com.lichong.service","com.lichong.aspect"})
public class JavaConfig {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
IUserService bean = applicationContext.getBean(IUserService.class);
bean.fun1();
bean.fun2();
bean.fun3("lili");
bean.fun4(new Param());
}
}
一些常用表达示例
表达式示例 | 说明 |
execution(public * *(..)) | 指定切入点,任意公共方法 |
execution(* set*(..)) | 指定切入点,任何一个以set开始的方法 |
execution(* com.*.*(..)) | 指定切入点,在com包下任意类的任意方法 |
execution(* com..*.*(..)) | 指定切入点,在com包及其子包下所有类的所有方法。 当..出现在类名中,后面必须使用*表示包下所有类 |
execution(* *.service.*.*(..)) | 指定切入点,一级包下service子包的所有类的所有方法 |
execution(* *.service.*.*(..)) | 指定切入点,所有包下service子包的所有类中的所有方法 |
全部通知类型的实际使用
@Component
@Aspect
public class UserAspectJ2 {
/**
* 前置通知
*/
@Before("within(com.lichong.service.impl.UserServiceImpl)")
public void before() {
System.out.println("before");
}
/**
* 后置通知
* @param res
*/
@AfterReturning(value = "within(com.lichong.service.impl.UserServiceImpl))", returning = "res")
public void afterReturning(Object res) {
System.out.println("afterReturning " + res);
}
/**
* 环绕通知
*
* @param point
* @return
* @throws Throwable
*/
@Around("within(com.lichong.service.impl.UserServiceImpl)")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("around before");
//参数数组
Object[] args = point.getArgs();
//方法返回值
Object res = point.proceed();
System.out.println("around after " + res);
return res;
}
/**
* 异常通知,抛出异常时将会通知
* @param ex
*/
@AfterThrowing(value = "within(com.lichong.service.impl.UserServiceImpl)",throwing = "ex")
public void atferThrowing(Exception ex) {
System.out.println("afterThrowing " + ex);
}
/**
* 最终通知,无论是否异常都会通知
*/
@After("within(com.lichong.service.impl.UserServiceImpl)")
public void after() {
System.out.println("after");
}
}
2.2、AOP源码粗读
很好,又到了痛苦的源码阅读时间了。
AnnotationConfigApplicationContext的refresh方法在IOC篇中就提到过,不过这次我们要关注的语句在下面,this.finishBeanFactoryInitialization(beanFactory);完成了对单例bean的、初始化操作。
public AnnotationConfigApplicationContext(Class... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
//完成单例bean的初始化操作
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
在这个方法中,最后一个语句,beanFactory.preInstantiateSingletons();完成了初始化,继续看它的内部逻辑
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver((strVal) -> {
return this.getEnvironment().resolvePlaceholders(strVal);
});
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
String[] var3 = weaverAwareNames;
int var4 = weaverAwareNames.length;
for(int var5 = 0; var5 < var4; ++var5) {
String weaverAwareName = var3[var5];
this.getBean(weaverAwareName);
}
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();
}
在这个方法里,依旧需要找到初始化bean的语句,那就是getbean方法。
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
while(true) {
String beanName;
Object bean;
do {
while(true) {
RootBeanDefinition bd;
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
while(var2.hasNext()) {
beanName = (String)var2.next();
Object singletonInstance = this.getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, this.getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
return;
}
beanName = (String)var2.next();
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract());
} while(!bd.isSingleton());
} while(bd.isLazyInit());
if (this.isFactoryBean(beanName)) {
bean = this.getBean("&" + beanName);
break;
}
this.getBean(beanName);
}
} while(!(bean instanceof FactoryBean));
FactoryBean<?> factory = (FactoryBean)bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
SmartFactoryBean var10000 = (SmartFactoryBean)factory;
((SmartFactoryBean)factory).getClass();
isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
this.getBean(beanName);
}
}
}
在geBean方法中只有doGetBean,在源码中,带有do的方法都是真正去执行具体操作的方法。在doGetBean方法中,初始化时所获取到的bean已经是空的,所以执行判断为空的部分。如果是单例类型,执行creatBean
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
return parentBeanFactory.getBean(nameToLookup);
}
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var12;
if (dependsOn != null) {
var12 = dependsOn;
int var13 = dependsOn.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dep = var12[var14];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
try {
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var31) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
}
}
}
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var12 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'");
}
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var30) {
throw new ScopeNotActiveException(beanName, scopeName, var30);
}
}
} catch (BeansException var32) {
beanCreation.tag("exception", var32.getClass().toString());
beanCreation.tag("message", String.valueOf(var32.getMessage()));
this.cleanupAfterBeanCreationFailure(beanName);
throw var32;
} finally {
beanCreation.end();
}
}
return this.adaptBeanInstance(name, beanInstance, requiredType);
}
看到doCreateBean方法,那肯定就是这个方法。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
this.populateBean(beanName, mbd, instanceWrapper);方法负责对象DI的实现
exposedObject = this.initializeBean(beanName, exposedObject, mbd);获取目标对象对应的代理类
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
this.populateBean(beanName, mbd, instanceWrapper);
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
this.invokeInitMethods(beanName, wrappedBean, mbd);请求初始化方法,所以AOP应该是在请求初始化方法之后,即wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);方法
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
在循环中最重要的还是current = processor.postProcessAfterInitialization(result, beanName);方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
核心方法肯定是this.wrapIfNecessary(bean, beanName, cacheKey);
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));创建代理对象
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
return proxyFactory.getProxy(classLoader);返回获取的代理对象
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);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (proxyFactory.isProxyTargetClass()) {
if (Proxy.isProxyClass(beanClass)) {
Class[] var6 = beanClass.getInterfaces();
int var7 = var6.length;
for(int var8 = 0; var8 < var7; ++var8) {
Class<?> ifc = var6[var8];
proxyFactory.addInterface(ifc);
}
}
} else if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
ClassLoader classLoader = this.getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader)classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
这个方法有两个实现,JDK与CGLib,这里只看JDK的实现。
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
显然JdkDynamicAopProxy继承了InvocationHandler,因此一定有一个invoke方法。
在invoke方法中,List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);是为了获取切点拦截。
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
Boolean var8;
try {
if (this.equalsDefined || !AopUtils.isEqualsMethod(method)) {
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
Integer var18 = this.hashCode();
return var18;
}
if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var17 = AopProxyUtils.ultimateTargetClass(this.advised);
return var17;
}
Object retVal;
if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
}
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
Object var12 = retVal;
return var12;
}
var8 = this.equals(args[0]);
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var8;
}
继续看cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);方法
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.MethodCacheKey(method);
List<Object> cached = (List)this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
这个方法获取了全部的切面拦截器的集合,并进行处理,然后返回。接下来回到JdkDynamicAopProxy。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList(advisors.length);
Class<?> actualClass = targetClass != null ? targetClass : method.getDeclaringClass();
Boolean hasIntroductions = null;
Advisor[] var9 = advisors;
int var10 = advisors.length;
for(int var11 = 0; var11 < var10; ++var11) {
Advisor advisor = var9[var11];
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher)mm).matches(method, actualClass, hasIntroductions);
} else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
MethodInterceptor[] var17 = interceptors;
int var18 = interceptors.length;
for(int var19 = 0; var19 < var18; ++var19) {
MethodInterceptor interceptor = var17[var19];
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
} else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
} else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor)advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
} else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
如果切点拦截不为空,则执行retVal = invocation.proceed();
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
Boolean var8;
try {
if (this.equalsDefined || !AopUtils.isEqualsMethod(method)) {
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
Integer var18 = this.hashCode();
return var18;
}
if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var17 = AopProxyUtils.ultimateTargetClass(this.advised);
return var17;
}
Object retVal;
if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
}
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
Object var12 = retVal;
return var12;
}
var8 = this.equals(args[0]);
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var8;
}
这个方法还是有两个实现,看JDK的那个。这个方法主要负责切点拦截的内容执行。
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
通过对源码的分析,可以得知,AOP通过代理的方式,在继承了InvocationHandler的invoke方法中,通过循环获取全部切点拦截,然后执行拦截内容和目标方法。
以上是关于Spring基础AOP面向切面编程的主要内容,如果未能解决你的问题,请参考以下文章
Spring框架系列 - 深入浅出Spring核心之面向切面编程(AOP)