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编程中,如果目标对象有实现接口,必须用接口接收。如果用实现类接收目标对象,会报错==