答案:
举例:
答案:
第一种,使用xml文件配置
:
<bean class="com.llg.UserService" id="userService">
第二种:使用注解
:
前提:需要配置扫描包ComponentScan,否则以下注解无效:
- @Component
而@Component又分为:
- @Controller
- @Service
- @Repository
第三种:@Bean
:
标注于方法,return一个对象,这个对象就会成为一个Bean,和@Component不同,@Component依赖反射来创建实例
//@Bean可以自己来控制Bean实例化的过程
@Bean
public DataSource dataSource(){
//...
// new xxx
//设置dataSource对象的各种属性
return dataSource;
}
第四种:@Import
:
//@Import只能用在类上
//@Import通过快速导入的方式实现把实例加入spring的IOC容器中
@Import({ 类名.class , 类名.class... })
public class TestDemo {
}
//对应的import的bean都将加入到spring容器中
PS:
- 作用域的配置可以在xml中使用scope属性
- 也可在使用@Scope注解
答案:
共有5个:
答案:
使用单例Bean,则不会每次都创建新的对象,因此在性能上有以下几点的优势:
答案:
demo演示:
定义一个单例Bean:其成员变量在某方法中有读写操作:
new两个线程,分别调用beanDemo方法:
简单分析下:线程1将username改成welcome:AAA后休眠的过程中,线程2将username改成welcome:QQQ,此时线程休眠结束,返回这个Bean的username属性,则都返回了welcome:QQQ:
如果将username改成beanDemo方法的局部变量,则没有此线程安全问题。
A1: 将Bean设置为多例
@Bean
@Scope("prototype")
...
A2: 将成员变量放在ThreadLocal(本地线程)中
//修改UserMapper类
public class UserMapper{
private ThreadLocal<String> username = new ThreadLocal<>(); //注意类型和之前的变化
public String beanDemo(String uname){
username.set("welcome:"+uname): //set修改
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
return username.get(); //get拿值
}
}
虽然现在线程1和线程2操作的是同一个UserMapper对象,但username是绑定在各自线程的,是各个线程独有的。
A3: 加同步锁,但这样会影响服务器的吞吐量,相当于把之前的并行改成了串行
A1: 构造器方式(反射)
比如使用xml或@Component定义一个Bean,则:
- BeanDefinition.beanClass
- 使用反射的new Instance,底层是在调用构造方法
A2: 静态工厂的方式
即定义Bean的时候配置下factory-method方法,则Spring实例化时会调用factory-method指定的方法去创建Bean,注意静态工厂指定的这个方法必须是静态的。
<bean class="cn.llg.beans.Person" id="person" factory-method="createPerson">
</bean>
A3: 实例工厂的方式(@Bean)
在factory-method的基础上再指定factory-bean,则实例化时,用factory-bean调用factory-method来实例化
<bean class="cn.llg.beans.Person" id="person"
factory-bean="personFactory"
factory-method="createPerson"
>
</bean>
别忘了BeanDefinition这个类,它里面就有对应属性存储factory-bean和factory-method
当使用@Bean时,则factoryBeanName就是你的那个配置类,而factoryMethodName就是@Bean注解下面的那个方法的方法名
。
A4: FactoryBean的方式
实现FactoryBean接口,重写getObject方法。
//之前的BeanFactory和FactoryBean区别时的那个FactoryBean
private class Car implements FactoryBean{
//...
@Overrride
public Object getObject() throws Exception{
return new Tank(); //汽车变坦克
}
@Override
public Class<?> getObjectType(){
return Tank.class;
}
}
总结就是四种,且后面这三种,我们可以自己控制Bean的创建,不再由Spring掌控。
一个个Bean创建出来,没有自动装配(纯净态Bean)时,如果它的一个属性是另一个对象,则没有自动装配时,这个属性自然为空。之前的这种方式是手动装配:
<bean id="bookService" class="com.llg.service.BookService>
" bookDao" ref="bookDao" />
bean>
----
PS:对应的Java代码:
public class BookService{
//...
private BookDao bookDao;
//...
}
简单说,自动装配即自动注入,就是Spring去建立Bean与Bean之间的依赖关系,对照上面的代码,自动注入即:
public class BookService{
//...
@Autowired
private BookDao bookDao;
//...
}
答案:
和
配置来定义依赖,且这些配置将覆盖自动注入<bean id="bookService" class="com.llg.service.BookService>
" bookDao" ref="bookDao1" />
bean>
//比如上面给bookService的bookDao属性装配,不管BookDao类型的Bean有多少,我就只要id为bookDao1的
在定义bean的xml中,输入autowired属性,就可以看到有5种:
在spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用autowire来配置自动装载模式。在Spring框架xml配置中共有5种自动装配:
no
:即默认不自动装配,需要手动设置ref属性来进行装配BeanbyName
:通过bean的名称进行自动装配,如果有一个bean的name和待装配的bean的property相同(对应代码中的setXXX后面的XXX,而不是直接找属性名
),则自动装配byType
:通过参数的类型来自动装配constructor
:利用构造函数进行装配,看构造函数的形参的类型去找
,找到多个时再按形参名自动装配public Class CarFactory{
private Tank tank;
public CarFactory(Tank tank) {
this.tank = tank; //按构造函数来自动装配
}
}
autodetect
:自动探测,若有构造方法,则按construct的方式,没有,则按byType的方式(在Spring3.0已经弃用)