IOC通过控制反转的方式,创建并管理bean【初始化,装配,销毁】
IOC容器的创建分为两个步骤: 1️⃣ 加载元数据注册BeanDifinition 2️⃣ 遍历BeanDifinition ,创建Bean
Bean AOP 1 什么是AOP?与OOP的关系?元数据: 包含需要创建bean所有配置信息,包括构造函数参数、属性值和特定于容器的信息,例如初始化方法、静态工厂方法名称等
BeanDefinition: 包含需要创建bean所有配置信息,包括构造函数参数、属性值和特定于容器的信息,例如初始化方法、静态工厂方法名称等
AOP【面向切面编程】,将那些与业务无关,但对多个对象产生影响的公共行为和逻辑,如权限认证,日志,事务等,抽取并封装成为一个可重用的模块,这个模块被成为切面【Aspect】。可以降低模块间的耦合度,同时提高系统的可维护性能。
与OOP都属于设计思想,OOP关注的类,从上至下 , AOP关注点是切面,从左至右
- 连接点:可以被增强的方法
- 切入点:实际被增强的方法
- 通知:需要增强的逻辑,根据通知的执行的顺序不同可分为不同的通知
- 切面:切入点和通知的整合。
前通知:在连接点之前运行的通知,但没有能力阻止执行流继续到连接点(除非它抛出异常)。
返回后通知:在连接点正常完成后运行的通知(例如,如果方法返回而没有抛出异常)。
抛出通知后:如果方法通过抛出异常退出,则运行通知。
After (finally) 通知:不管连接点退出的方式(正常或异常返回)都将运行的通知。
环绕通知:环绕连接点的通知,环绕通知可以在方法调用前后执行自定义行为。它还负责选择是继续连接点还是通过返回自己的返回值或抛出异常来缩短建议的方法执行。
4 AOP 实现的机制JDK动态代理或CGLIB动态代理
5 JDK动态代理或CGLIB动态代理的区别- JDK动态代理
只提供接口的代理,会在运行时,生成动态代理类,实现接口中所有方法增强代码。调用时用代理类进行增强,然后通过反射的方式调用目标方法 - CGLIB动态代理
没有实现接口,底层通过ASM在运行时动态的生成目标类的一个子类,同时生成多个其他相关的类【为提高cglib动态代理调用的效率】。重写父类的所有子类进行增强。调用代理类时,通过调用父类的方法进行方法的增强
因为CGLIB是通过继承父类的方式实现动态代理,意味着父类标记了final的方法无法增强实现逻辑
配置上标注 @EnableAspectJAutoProxy,可以基于注解模式来使用AOP
7 AOP內部調用失效的原因?如何解决?在同一个类中 ,调用使用注解方式的AOP功能的方法,目标方法的注解则会失效,即无法实现预期的功能控制,例如事务、权限等。
失效的原因:
AOP实际上是通过代理的对象来实现方法,而非实际的目标对象或者操作实例对象。 但是在类内部的方法中,调用同一个类中定义的方法,则调用的是当前的对象,而不是代理对象,则注解失效,AOP功能失效
解决方法:
重新获得代理对象,通过代理对象来调用方法
- 暴露当前代理对象到本地线程,从AopContext 获取本地线程中存储的代理对象 ,AopContenxt.Current
- 开启方式为@EnableAspectJAutoProxy(exposeProxy = true)
1:Bean初始化时,通过BeanPostProcesser.postProcessAfterInitialization()方法,创建动态代理类
//创建动态代理的实现类:AbstractAutoProxyCreator
//关键方法
@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;
}
// 根据当前bean找到匹配的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;
}
在这里插入代码片



