Some questions in learnning Spring

Some questions in learnning Spring

  • 问题1:

Test3.java中

User user = ac1.getBean("user", User.class);

会创建两个对象user和person

answer:在new ClassPathXmlApplicationContext的时候会把配置文件中所有的bean创建完成,因为bean的lazy-init默认属性是false,在初始化的时候已经创建完成,如果只想使用一个bean创建一个bean,应该在xml的配置文件中把所有的bean的lazy-init属性全部设置为true。


  • 问题2:

错误:org.springframework.dao.EmptyResultDataAccessException

原因:缺少jar包


      org.springframework
      spring-framework-bom
      4.3.8.RELEASE
    

  • 问题3:

ioc容器和DI的关系和区别

ioc是一种思想,也就是控制反转。把对象交给spring去创建实例化就是一种控制反转。那么把对象交给spring创建时,spring只会用无参的构造器去创建,该对象的属性spring并不知道,因此也就需要DI(dependency injection)依赖注入了。

DI的作用是给对象属性赋值,也正因为有IOC,所以才会有DI的出现加以补充。

其中DI有三种方式去实现,

  • 通过带参构造器给对象属性赋值
  • 通过set方法给对象属性赋值
  • 通过p:名称控制给对象赋值

  • 注释写在接口上,使用文档注释。


  • 问题4:

错误:at org.junit.internal.builders.JUnit4Builder.runnerForClass

原因:sql语句写错,粗心大意

解决方法:重写Dao的实现类,修改test测试类


  • 问题5:

==为什么输出两次 ”图图吃饭了“?==

Test类:

@Test
    public void userTest1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        User1 user = applicationContext.getBean("user", User1.class);
        user.eat(user.getName());
    }

User类

public class User {
    @Autowired
    private String name;
    @Autowired
    public void eat(String name){
        System.out.println(name+"吃饭啦!");
    }
}

bean.xml


        
    
    
        
    

实验:

@Test
    public void userTest1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//        System.out.println("----------------");
//        User1 user = applicationContext.getBean("user", User1.class);
//        System.out.println("----------------");
//        System.out.println(user);
//        System.out.println("----------------");
//        user.eat(user.getName());
    }

//输出结果:
   //创建User对象!
   //图图吃饭啦!

​ 当我们把下面的都注释掉后,只留下根据bean.xml创建容器的代码,编译运行后发现,输出了两行

“创建对象啦!”

”图图吃饭啦!“

因此我猜测原因是因为在创建ioc容器的时候,会把bean.xml里所有定义的类都调用类的无参构造器实例化,并且把类中所有标有注释@Autowired的方法都执行一遍。。。


  • 问题6

@PostConstruct ---> init-method=" " //初始化方法,在构造器和@Autowired标记的方法后执行。

那么问题来了:

User类

    @PostConstruct
    public void sleep(){
        System.out.println("刚起床就睡觉了");
    }

Test类

public void userTest1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//        System.out.println("----------------");
        User1 user = applicationContext.getBean("user", User1.class);
    
    //执行结果:
          //创建User对象!
          //图图吃饭啦!

==初始化方法并没有执行,为什么?==

原因:@PostConstruct注解在JDK1.8以上版本无效。

jdk8以上的jdk使用了新的module系统,javax.annotation默认不可见。


  • 问题7

public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    public DataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        //以下ds调用的方法哪里来的?
        ds.setDriverClassName(this.driver);
        ds.setUrl(this.url);
        ds.setUsername(this.username);
        ds.setPassword(this.password);
        return ds;
    }
}

Answer:

DruidDataSource类中没有这些方法,不过他的父类DruidAbstractDataSource中有这些方法。


  • 问题8

异常:
Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'iUserServiceImpl' is expected to be of type 'com.itheima.service.impl.IUserServiceImpl' but was actually of type 'com.sun.proxy.$Proxy4'

错误原因:jdk的动态代理不支持类注入,只支持接口方式注入,如果确时不想用spring提供的动态代理,则此时可以选择用cglib代理解决。必须引入cglib的外部包。

而在测试的时候,通过getBean的方法获取了一个实现类的对象,所以报错。

==再Aop编程中,如果目标对象有实现接口,必须用接口接收。如果用实现类接收目标对象,会报错==

你可能感兴趣的:(Some questions in learnning Spring)