公司最新的项目要引入阿里规约,业务层注入属性的方式从原来的属性注入变成了Spring4推荐的构造器注入,代码的不规范导致我出现了循环引用的问题:
是这两个地方出现了问题
TaskImageService
package service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdls.carp.business.dao.TaskImageDao;
import com.cdls.carp.business.entity.TaskImageEntity;
import com.cdls.carp.business.service.TaskImageService;
import com.cdls.carp.business.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TaskImageServiceImpl extends ServiceImpl<TaskImageDao, TaskImageEntity> implements TaskImageService {
private final TaskService taskService;
@Autowired
public TaskImageServiceImpl(TaskService taskService) {
this.taskService = taskService;
}
}
TaskService
package service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdls.carp.business.dao.TaskDao;
import com.cdls.carp.business.service.TaskImageService;
import com.cdls.carp.business.service.TaskLogService;
import com.cdls.carp.business.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskServiceImpl extends ServiceImpl<TaskDao, TaskEntity> implements TaskService {
private final TaskImageService taskImageService;
@Autowired
public TaskServiceImpl(TaskImageService taskImageService) {
this.taskImageService = taskImageService;
}
}
于是我使用属性注入的方式
TaskImageService
package service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdls.carp.business.dao.TaskImageDao;
import com.cdls.carp.business.entity.TaskImageEntity;
import com.cdls.carp.business.service.TaskImageService;
import com.cdls.carp.business.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TaskImageServiceImpl extends ServiceImpl<TaskImageDao, TaskImageEntity> implements TaskImageService {
@Autowired
private TaskService taskService;
}
TaskService
package service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdls.carp.business.dao.TaskDao;
import com.cdls.carp.business.service.TaskImageService;
import com.cdls.carp.business.service.TaskLogService;
import com.cdls.carp.business.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskServiceImpl extends ServiceImpl<TaskDao, TaskEntity> implements TaskService {
@Autowired
private TaskImageService taskImageService;
}
结果又可以运行了,我当时怀疑Spring Ioc的问题,后来才发现其实是类的实例机制出现了错误,我们举个例子,
有两个类,分别是TestA 和 TestB,他们都拥有对方的属性
/**
* @author Tobu
*/
public class TestA {
private TestB testB;
public TestA() {
}
public TestA(TestB testB) {
this.testB = testB;
}
public void setTestB(TestB testB) {
this.testB = testB;
}
}
/**
* @author Tobu
*/
public class TestB {
private TestA testA;
public TestB() {
}
public TestB(TestA testA) {
this.testA = testA;
}
public void setTestA(TestA testA) {
this.testA = testA;
}
}
例如我们现在需要TestA,我现在是用构造器来创建TestA
恍然大悟,如果是这样的话我确实是进行了循环注入,如果我使用默认的空构造器,那么就不再是构造器注入而是setter注入了,
解决方式就是把业务逻辑挪到其中的一个类中,就不会出现循环注入的问题
setter注入(空构造器+set方法):
/**
* @author Tobu
*/
public class TestMain {
public static void main(String[] args) {
TestA testA = new TestA();
testA.setTestB(new TestB());
}
}
属性注入(使用反射机制)
import java.lang.reflect.Field;
/**
* @author Tobu
*/
public class TestMain {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// 创建testA对象
TestA testA2 = new TestA();
// 返回testA
Class<TestA> testA = (Class<TestA>) Class.forName("TestA");
// 获取所有的属性
Field[] fields = testA.getDeclaredFields();
// 设置属性可以操作并且设置值
fields[0].setAccessible(true);
fields[0].set(testA2, new TestB());
// 实例化对象
TestA testA1 = testA.newInstance();
}
}