一些注解类
@ComponentScan
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String value() default "";
}
@Component
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
@Scope
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {
String value() default "";
}
@Autowired
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
建立BeanDefinition
BeanDefinition与Bean的关系, 就好比类与对象的关系. 类在spring的数据结构就是BeanDefinition.
public class BeanDefinition {
private Class type;
private String scope;
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
MyApplicationContext类
public class MyApplicationContext {
private Class configClass;
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();
public MyApplicationContext(Class configClass) {
this.configClass = configClass;
//扫描类的注解
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
path = path.replace(".","/");
ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
System.out.println(file);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
String fileName = f.getAbsolutePath();
if (fileName.endsWith(".class")) {
String className = (path + "/" + f.getName().substring(0,f.getName().indexOf(".class"))).replace("/",".");
try {
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
String beanName = clazz.getAnnotation(Component.class).value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
}
//create所有的单例bean
beanDefinitionMap.keySet().forEach(beanName -> {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,bean);
}
});
}
//创建bean
public Object createBean(String beanName,BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
//简易DI
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)) {
f.setAccessible(true);
//把带autowired注解的字段的实例设置为getBean(f.getName())
f.set(instance,getBean(f.getName()));
}
}
return instance;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
//getBean方法实现
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new NullPointerException();
}
String scope = beanDefinition.getScope();
//单例
if (scope.equals("singleton")) {
Object bean = singletonObjects.get(beanName);
/*
此处空处理的原因:比如,在创建UserService的bean的时候,createBean方法中会进行依赖注入OrderService,
而此时会调用getBean方法(f.set(instance,getBean(f.getName()));),但这时可能单例库里还没有OrderService,
所以要进行空处理并且将其加入单例库
*/
//未解决循环依赖问题
if (bean == null) {
bean = createBean(beanName,beanDefinition);
}
return bean;
}
return createBean(beanName,beanDefinition);
}
}
Aware回调
在spring文件夹中创建接口BeanNameAware
public interface BeanNameAware {
void setBeanName(String beanName);
}
MyApplicationContext中的createBean方法写入
public Object createBean(String beanName,BeanDefinition beanDefinition) {
...
//beanName的aware回调
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
...
}
service类要实现BeanNameAware,才能进行aware回调
Spring的初始化
创建接口InitializeBean,需要service类实现该接口
public interface InitializeBean {
void afterPropertiesSet();
}
MyApplicationContext中的createBean方法写入
public Object createBean(String beanName,BeanDefinition beanDefinition) {
...
//类的初始化
if (instance instanceof InitializeBean) {
((InitializeBean)instance).afterPropertiesSet();
}
...
}
BeanPostProcessor机制
创建接口BeanPostProcessor
public interface BeanPostProcessor {
void postProcessorBeforeInitialization(String beanName,Object bean);
void postProcessorAfterInitialization(String beanName,Object bean);
}
创建自定义的MyBeanPostProcessor类实现BeanPostProcessor接口及其方法,在其中对service类实现操作,并将MyBeanPostProcessor加入Spring容器(@Component)
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public void postProcessorBeforeInitialization(String beanName, Object bean) {
//根据beanName名字判断/根据bean类型判断
//操作
}
@Override
public void postProcessorAfterInitialization(String beanName, Object bean) {
}
}
创建BeanPostProcessor的list集合以放入实现该接口的实例。
扫描类注解时加入(在MyApplicationContext的构造方法)
...
private ArrayList<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
...
if (clazz.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(clazz)) { //该类实现接口
BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
beanPostProcessors.add(instance);
}
String beanName = clazz.getAnnotation(Component.class).value();
if ("".equals(beanName)) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
...
在createBean方法类初始化前后实现BeanPostProcessor实现类的自定义方法中的操作
...
//beanName的aware回调
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
//实现BeanPostProcessor方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
beanPostProcessor.postProcessorBeforeInitialization(beanName,instance);
}
//类的初始化
if (instance instanceof InitializeBean) {
((InitializeBean)instance).afterPropertiesSet();
}
//实现BeanPostProcessor方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
beanPostProcessor.postProcessorAfterInitialization(beanName,instance);
}
...
AOP机制
现在createBean方法return的是一个普通对象,而AOP要求返回的对象是一个代理对象
使用jdk代理(service类需要接口)
目标:createBean方法经过BeanPostProcessor实现类的方法后返回代理对象
修改接口BeanPostProcessor返回值
public interface BeanPostProcessor {
Object postProcessorBeforeInitialization(String beanName,Object bean);
Object postProcessorAfterInitialization(String beanName,Object bean);
}
修改MyBeanPostProcessor类
代理逻辑中实现切面方法
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessorBeforeInitialization(String beanName, Object bean) {
return bean;
}
@Override
public Object postProcessorAfterInitialization(String beanName, Object bean) {
if (beanName.equals("userService")) {
Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//切面逻辑
return method.invoke(bean,args);
}
});
return proxyInstance; //return一个代理对象
}
return bean;
}
}
修改createBean方法
//beanName的aware回调
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
//实现BeanPostProcessor方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
instance = beanPostProcessor.postProcessorBeforeInitialization(beanName,instance);
}
//类的初始化
if (instance instanceof InitializeBean) {
((InitializeBean)instance).afterPropertiesSet();
}
//实现BeanPostProcessor方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
instance = beanPostProcessor.postProcessorAfterInitialization(beanName,instance);
}
return instance;
如果经过BeanPostProcessor方法,此时return的instance就是我们自定义的代理对象
Bean的生命周期
bean创建的生命周期
service.class
-> 推断构造方法
-> 对象
-> DI
-> 初始化前(@PostConstruct)
-> 初始化 (afterPropertiesSet方法)
-> 初始化后 (AOP)
-> (代理对象)
-> 放入单例池
-> bean对象
初始化前和初始化时
假设service类中有一个属性private User admin,如何给在bean创建的时候给这个属性赋值?
如果利用Autowired,spring并不知道该给admin赋值为什么(比如查询数据库得到赋值),所以要自定义方法来给admin赋值。
实现1:
此时可以写一个方法f,在f中实现admin的赋值逻辑,并在初始化前进行f的调用。
如何进行初始化前调用?在方法上使用@PostConstruct注解
逻辑如下:
for(Method method: Service. getClass). getDeclaredMethods()) {
if (method.isAnnotationPresent(PostConstruct.class)) {
method.invoke(userService1,null);
}
实现2:
service类实现InitializingBean接口,重写其中的afterPropertiesSet方法,在方法中实现逻辑赋值
该方法会在spring初始化的时候被调用
该方法的实现逻辑:
进入AbstractAutowiredCapableBeanFactory类的doCreateBean方法,
用构造方法得到对象实例,
解决循环依赖问题,
populatedBean方法属性填充,
initializeBean方法 {
aware回调,
初始化前,
初始化:判断有没有实现InitializingBean,执行afterPropertiesSet方法,
初始化后
},
......
推断构造方法
推断构造方法的底层原理?
Q1:private OrderService orderService并未加@Autowired注解。如果有1,输出什么?如果有1、2,输出什么?如果有2、3,输出什么?
@Component
public class UserService {
private OrderService orderService;
1️⃣public UserService() {
System.out.println(0);
}
2️⃣public UserService(OrderService orderService) {
this.orderService = orderService;
System.out.println(1);
}
3️⃣public UserService(OrderService orderService, OrderService orderService1) {
this.orderService = orderService;
System.out.println(2);
}
...
结果:
1.输出0,并且属性orderService为null。
2.输出1,并且属性orderService不为空。
3.报错
原因分析:
如过仅存在一个构造方法,则spring会调用该构造方法;
如果存在多个构造方法,则spring会在这些构造方法中寻找无参构造方法。如果找到就会调用,找不到就会报错。
Q2:如何让spring调用指定的构造方法?
在想被调用的构造方法加上@Autowired注解
Q3:前面结果2属性orderService不为null,spring如何为属性赋值?
属性如果不是bean,则会报错;
属性如果是单例bean,就会去单例池里寻找,如果有就会赋值,没有会创建bean;
属性如果不是单例bean,就会直接创建bean
Q4:在map<beanName,Bean对象>单例池中寻找bean的时候,如果根据beanName查找不可行,因为public UserService(OrderService orderService)中形参名字可以随便取。所以根据类型来取得。但是根据类型获取会出现一个value对应多个key的情况,或者多个value都是同一类型。如何解决?
@Component
public class OrderService {}
@Bean
public OrderService orderService1(){return new OrderService();}
@Bean
public OrderService orderService2(){return new OrderService();}
//这三个orderService不是一个对象,但是类型相同(即多个value都是同一类型)
解决方法:先根据type查找。如果type查到有多个,就根据name筛选;如果只查到一个,就直接赋值。
因此,推断构造方法有两步:
1.选择构造方法
2.实现构造方法入参属性赋值
依赖注入
依赖注入的原理?
1.查找属性
2.与构造方法入参相同的方法进行属性赋值
代理对象
Q1:放入单例池的是原对象还是代理对象?
如果需要实现AOP,则放入的是代理对象;
如果不需要,则放入的是原对象
Q2:代理对象被标记@Autowired的属性的值是否为空?
属性值为空,因为代理对象产生后并未进行DI就加入了单例池。
Q3:如果为空,那为什么打印输出该属性的时候并不为空?
代理类创建时有一个target属性,并将代理类的普通类赋值给该target属性。调用test方法时,执行的是代理类的test方法。代理类的test方法先进行AOP,然后调用target.test(),即调用普通类的test方法。target是普通类进行了DI,因此避免了属性为空的问题。
class UserServiceProxy extends UserService {
UserService target;
public void test(){
//切面逻辑@Before
//target.test();//普通对象.test()
}
}
Q4:Q3为什么通过建立target属性来解决而不是直接调用super.test()?
??我也不清楚
Q5:代理类可以不继承普通类吗?(cglib代理)
不可以。不继承就不能将代理类强制转换为普通类了。
UserService userService = (UserService) applicationContext.getBean("userService")
事务管理
事务切面逻辑:
添加@Transaction注解开启事务
-> 事务管理器 新建数据库连接connection
-> connection.autocommit = false
-> target.test()
-> connection.commit()/rollback()
Q1:为什么spring会让事务管理器建立连接,而不直接让jdbcTemplate建立连接?
因为jdbcTemplate建立的连接默认autocommit = true,会直接提交,起不到事务管理的作用
Q2:在service类中添加如下方法,调用test方法,a方法的@Transactional注解会不会起作用?
@Transactional
public void test() {
jdbcTemplate.execute("...");
a();
}
@Transactional(propagation = Propagation.NEVER)
public void a {
jdbcTemplate.execute("...");
}
...
不会。
-> 调用service.test()
-> 进入代理类的test方法
-> 代理了执行target.test()
-> 由于target为普通service类,@Transactional注解不起作用
-> 不会抛出异常(正常情况下@Transactional(propagation = Propagation.NEVER)会导致抛出异常)为什么test方法的@Transactional注解有用?
因为调用service.test()时执行方法的是代理类,会去处理@Transactional注解。而执行a方法的时候只是普通类。
Q3:如何解决Q2的问题?
1.拆分类:拆分出另外一个类s1,在s1中写a方法,再将s类注入原service(s)类,在test方法中调用s.a()即可
2.自己注入自己
3.其他方法拿到当前类代理对象,例如AopContext.currentProxy()
@Autowired
private Service s1;
@Transactional
public void test() {
jdbcTemplate.execute("...");
s1.a();
}
=================================
@Autowired
private Service s;
@Transactional
public void test() {
jdbcTemplate.execute("...");
s.a();
}
Q4:@Configuration注解对事务管理的影响(config类不加@Configuration注解错误问题)
我们知道,
1️⃣ spring的事务管理器创建connection放在LocalThread<Map<Datasource,connection>>中。
“为什么泛形里面放的是map而不直接是connection?
因为现实工程中可能会使用多种datasource。”
2️⃣ 不加@Configuration注解时,jdbcTemplate和事务管理器创建的datasource对象不是同一个对象,只有事务管理器创建出来的对象才有事务处理的功能,jdbcTemplate的autocommit = true因此,加上@Configuration注解会使jdbcTemplate调用的是事务管理器创建的datasource,而不会自己再创建一个新的datasource,避免事务管理的失效。
Q5:@Configuration注解解决Q4的原理?
@Configuration,AOP,@Lazy都是使用的动态代理机制
AppConfig加上@Configuration注解之后会生成一个动态代理类
public classAppConfig {//config类
@Bean
public IdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource());
return transactionManager;
}
@Bean
public void datasource() {
...
}
...
class UserServiceProxy extends AppConfig{//config代理类
UserService target;
public void jdbcTemplate(){
//代理逻辑
super.jdbcTemplate();
}
public void datasource(){
//代理逻辑
}
}
config类中jdbcTemplate()和transactionManager()方法中的datasource()方法都是代理类调用的
代理类来调用jdbcTemplate()和datasource()方法。
代理类在调用这两个方法时,会首先执行代理逻辑。即:在执行jdbcTemplate()方法时,先检测spring容器里面有没有datasource,如果有就直接返回spring容器中的datasource;如果没有就调用datasource()方法去创建一个datasource并放入spring容器。
通过这种方式来保证jdbcTemplate()和datasource()得到的是同一个datasource
//在config类中
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate (dataSource)());
}
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource1());
return transactionManager;
}
上述代码的情况:如果jdbcTemplate()和transactionManager()方法中的datasource不是同一个,即使加@Configuration注解也会出现Q4错误
循环依赖
三级缓存(三个map)
singletonobjects(即单例池) -> 保存拥有完整生命周期的bean
earlySingletonobjects -> bean被循环依赖,提前产生一个代理对象,保存到二级缓存,保证单例
singletonFactories -> 打破循环,先存到三级缓存,出现循环依赖的情况下才能拿到被依赖的对象
引入
背景:AService类注入了BService类属性,BService类注入了AService类属性
解决方法:利用一个map解决循环依赖问题
AService的Bean的生命周期:
- 实例化--->AService普通对象--->map.put("AService",AService普通对象)
- 填充bService--->单例池Map--->创建BService
BService的Bean的生命周期:- 实例化--->普通对象
- 填充aService--->单例池Map--->map--->AService普通对象
- 填充其他属性
- 做一些其他的事情(AOP)---> AService的代理对象
- 添加到单例池
- 填充其他属性
- 做一些其他的事情
- 添加到单例池
出现问题:注入bService的AService属性是AService的普通对象,而加入单例池是AService的代理对象
解决方法:未出现循环依赖的bean不提前进行AOP,只有出现循环依赖的bean提前进行AOP。加入creatingSet存放正在进行初始化的bean,在第2.2通过检查creatingSet判断循环依赖,决定是否提前进行AOP。
- creatingSet<AService›
- 实例化-->AService普通对象
- 填充bService--->单例池Map--->创建BService
BService的Bean的生命周期:
2.1 实例化-->普通对象
2.2 填充aService--->单例池Map--->creatingSet--->AService出现了循环依赖--->AOP---> aService代理对象--->添加到单例池
2.3 填充其他属性
2.4 做一些其他的事情(AOP)
2.5 添加到单例池 - 填充其他属性
*5. 做一些其他的事情(AOP)--->AService代理对象 - 添加到单例池*
- creatingSet.remove<'AService'>
出现问题:是否应该将5、6提前到2.2斜体部分?
答案:不应该在2.2斜体部分加入单例池。
因为存在一些潜在的问题,例如:
1. 此时aService普通对象还未初始化完成,代理对象创建过程中可能拿不到普通对象
2. 此时aService普通对象还未初始化完成,因此aService代理对象中的target属性为空或不完整。此时如果有另外一个线程使用单例池中的aService代理对象,就会出现问题。
二级缓存
出现问题:
背景:如果aService依赖bService和cService,而bService和cService都依赖aService,那bService和cService在初始化的时候都需要创建aService的代理对象,与单例模式产生矛盾。
解决方法:利用第二级缓存earlySingletonobjects,在b需要a的时候创建a的代理对象并将其加入earlySingletonobjects,c在需要a的时候直接从二级缓存里面拿。
二级缓存的作用:存储出现循环依赖问题时还未完成完整生命周期的早期的bean对象,保持单例性
问题:什么时候将aService代理对象加入单例池?
答案:在aService填充完所有属性并进行完其他的事情(如AOP)之后,earlySingletonobjects.get(AService)得到a的代理对象,加入单例池
问题:第四步“填充其他属性”是aService普通对象还是代理对象?
答案:普通对象。代理对象存在的意义仅仅是执行切面逻辑。
三级缓存
三级缓存的作用是打破循环。
singletonFactories里存放的是(beanName,lambda表达式):
singletonFactories.put('AService',()-> getEarlyBeanReference(beanName,mbd,AService普通对象))
源码:
//判断是否是单例,是否支持循环依赖(默认true),是否正在被创建
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
//如果都是
if(earlySingletonExposure) {
if(logger.isTraceEnabled()) {
Logger.trace("Eagerly caching bean '" + beanName + "'to allow for resolving potential circular references");
}
//加入三级缓存
addSingletonFactory(beanName,() -> getEarlyBeanReference(beanName, mbd,
bean));
}
如果在一二级缓存里面都没找到,就去第三级缓存找,执行()-> getEarlyBeanReference(beanName,mbd,AService普通对象)。
如果该bean需要进行AOP,那执行的结果是进行AOP,创建代理对象。
如果不需要,那执行的结果是返回普通对象。
最后将代理/普通对象放入二级缓存。
a填充b的属性时,会调用getSingleton方法:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonobject = this. singletonobjects.get (beanName);
if(singletonObject == null &d isSingletonCurrentlyInCreation(beanName)) {//当前索要的对象为空且正在创建中,即出现了循环依赖
singletonObject = this. earlySingletonobjects. get (beanName);
if (singletonobject == null && allowEarlyReference) {
synchronized (this. singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonobject = this. singletonobjects.get (beanName);
if (singletonobject == null) {
singletonobject = this. earlySingletonobjects.get (beanName);
if (singletonObject == null) {//二级缓存没有
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {//去三级缓存找
singletonobject = singletonFactory.getobject;
this. earlySingletonobjects. put (beanName, singLetonobject);//加入二级缓存中
this. singletonFactories. remove (beanName);//从三级缓存中移除,即移除lambda表达式
}
}
}
}
}
}
}
}
return singletonObject;
}
为什么要从三级缓存中移除?
因为对象是单例的,lambda表达式(()-> getEarlyBeanReference(beanName,mbd,AService普通对象))只需要执行一次,保证单例。
同理,当需要去三级缓存中存的时候,二级缓存中也会执行移除
例如:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert. notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this. singletonobjects. containsKey(beanName)) {
this. singletonFactories put(beanName, singletonFactory);
this.earlySingleton0bjects.remove(beanName);
this.registeredSingletons.add (beanName);
}
}
}
5、6步之间还会调用getSingleton方法,从二级缓存中拿到代理对象
总结:
对象创建时,先存在三级缓存中,在出现循环依赖的时候去三级缓存取,然后执行取到的lambda表达式并执行,进行AOP得到代理对象,然后将代理对象存进二级缓存,然后执行接下来的创建步骤,创建完成后放入一级缓存。
Map:earlyProxyReferences
如果在2.2提前进行AOP,那原本该进行AOP的时候(第5步)如何进行?
@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;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean. getClass), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cachekey);
}
通过一个map "earlyProxyReferences"来区分bean是否进行过AOP。
getEarlyBeanReference方法是lambda表达式调用的方法。如果提前进行AOP,该方法被调用,对该bean产生一个cacheKey放入earlyProxyReferences中,并且调用wrapIfNecessary方法。
postProcessAfterInitialization是正常AOP调用的方法。if的意义在于判断earlyProxyReferences中是否有该bean的cacheKey。如果有,就直接返回普通对象(此处不必着急返回代理对象,因为5、6步之间还会调用getSingleton方法,从二级缓存中拿到代理对象);如果没有,即this.earlyProxyReferences. remove(cacheKey) == null,就调用wrapIfNecessary方法。
@Lazy
问题:如果在a构造方法里(a初始化的时候)加入this.bService = bService,则根本创建不出来a的普通对象,因此spring解决不了循环依赖问题。
@Component
public class AService {
private BService bService;
@Lazy
public AService(BService bService) {
this.bService = bService;
}
public void test() {
bService.toString();
}
...
解决方法:加上@Lazy注解。加注解后,在创建a的bean的时候,会创建一个b的代理对象注入a,不会出现循环依赖问题。等到真正调用关于b的方法(例如test方法)的时候,b才会真正被创建出来。
*也可以解决@Async报错问题。