springdependency-injectioncglibconstructor-injection

How to use Constructor Injection on Spring 3.2.9?


to everybody click my question, thank you(my eng is bad).

The spring version Im working on is 3.2.9. And it's been used Field Injection like

@Controller
@RequestMapping("/test/something")
public class TestController {

    @Autowired
    private TestService testService;

}

But Recently, I knew Using the Constructor Injection is way safey and better than Field Injection and Setter Injection.

So I've been trying to use Constructor Injection but it doesnt work.

I tried this


@Controller
@RequestMapping("/test/something")
public class TestController {

    private final TestService testService;

    @Autowired
    public TestController (TestService testService){
         this.testService = testService;
    }

}

The console keeps throwing up bunch of error.

Which is BeanCreationException(Error creating bean with name...), AopConfigException(could not generate CGLIB...), IllegalArgumentException(Super class has no null constructor but no arguments were given).

Also, I've been trying to take off the 'final' and '@Autowired'. It's same. Doesnt work.

1.
@Controller
@RequestMapping("/test/something")
public class TestController {

    @Autowired
    private TestService testService;

    @RequestMapping(value="/happy.do")
    public ModelAndView happything(){
        
       ModelAndView mav = new ModelAndView();

       List<HashMap<String, Object>> happyListMap = testService.getHappyList();

       mav.addObject("happyListMap", happyListMap);
       mav.setViewName("world/happy/list");
       return mav;
    }

}

2.
public interface TestService {

    List<HashMap<String, Object>> getHappyList();

}

3.
@Service("TestService")
public class TestServiceImpl implements TestService {

    @Autowired
    private TestMapper testMapper;

    @Autowired
    private HelpMapper helpMapper;

    @Override
    public List<HashMap<String, Object>> getHappyList(){

        int happyPoint = helpMapper.selectHowMuchHappyYouAre();

        List<HashMap<String, Object>> happyListMap = testMapper.selectHappyList(happyPoint);

        return happyListMap;
    }

}

4.
@Mapper("TestMapper")
public interface TestMapper {

    List<HashMap<String, Object>> selectHappyList(int happyPoint);

}

5.
testMapper.xml - myBatis

/* select query */

It's not supposed to work on spring 3.2.9? Should I just use Field Injection?

(Additing, the project can't use Lombok.)


Solution

  • You are using an ancient and unsupported version of Spring, which I highly recommend to upgrade to something that is supported (like 5.3.x or even the 6 although that last one might be a bridge too far).

    The error tells you what is wrong, albeit a bit of a cryptic one.

    BeanCreationException(Error creating bean with name...), AopConfigException(could not generate CGLIB...), IllegalArgumentException(Super class has no null constructor but no arguments were given).
    

    The null constructor is a default no-args constructor as that is still needed in this version of Spring. The proxy needs a no-args constructor, so you need to add it. (This restriction has been lifted in later versions of Spring).

    @Controller
    @RequestMapping("/test/something")
    public class TestController {
    
        private final TestService testService;
    
        public TestController() {
            this(null);
        }
    
        @Autowired
        public TestController (TestService testService){
             this.testService = testService;
        }
    
    }
    

    The controller above has a no-args constructor added, as your field is final you need to assign a value to it. I find it always better to chain the constructor and thus call this(null) which will invoke the TestController(TestService testService) constructor with a null value.

    However the fact that you need this constructor highlights, imho, a bigger issue you have and that is that you are using AOP to apply some logic to classes. It appears to me, without knowing what you are doing, that you are applying it too broadly.