//对beans的配置多了一个default-lazy-init="true"
//问个问题:如果beans的default-lazy-init="true"执行之后会怎样?
//会影响到谁?会怎样影响它们?
<beans xmlns="" xmlns:xsi="" xsi:schemaLocation=""
default-lazy-init="true">
//该bean标签被执行之后会怎样?
//调用CAAccountServiceImpl类的无参构造方法
//构造出一个实例accountService
//然后调用类中accountDao属性的setter方法给该属性赋值(也就是使实例完备)
//但由于accountDao是一个自定义类的属性,很特别
//那就只能去到对应的类中构造出一个实例出来
//然后再赋值过去
//不是一直好奇写好的bean类如何实例化的,如何调用方法的么?
//答案就在这里
//就是不直接操作,直接操作就搞死了嘛//间接才更加高级
//ref一般表示对id值的引用
//而这里ref有特别的含义:要赋值给属性的那个实例
//这里的name表示:被赋值的那个属性
//这里究竟发生了什么?
//我有两个类
//在其中一个类中,我要把另外一个类的实例作为本类中的一个属性
//使其大致就是这样
//问题是我为什么这样做呢???
//这里我可以实例化出很多的实例
//我还可以把这些实例放在容器中
<bean id="accountService" class="com.wiley.beginningspring.ch2.~CAAccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
//这里对bean的配置多了一个lazy-init="false"
//该标签执行后,将调用类AccountDaoInMemoryImpl的无参构造函数
//构造出一个实例accountDao
//这里肯定存在一个顺序:
//我是先实例accountService呢?还是先实例accountDao呢
//傻子也看的出来,应该先实例出accountDao,然后再实例accountService
//因为这样调用setter方法时候,才显得入情入理!!
//确定必须是这种顺序之后,我怎么保证这种顺序呢?
//lazy表示懒,懒的人总是磨磨蹭蹭到后面才来的
//lazy表示的不是懒,而是作为懒的表现的先与后
//所以这里多了个lazy-init="false":表面意思=不后初始化=先初始化
//作为一个被依赖项我们更希望预先就创建出来!!!
//所以这里多了个lazy-init="false"
//那为什么要设置default-lazy-init="true"呢?
//它是设置给beans的,这意味着,将会管理到下面的所有的bean
//defalut表示默认
//所以default-lazy-init="true"表示,默认就是后初始化(取值true/false的特性连起来才有更强的语义)
//设置了这个反而就麻烦了
//意味着我们必须在这里设置这个lazy-init="false"
//注意!注意!通常情况下,我们什么都没设置,就说明:不设置的情况下:default-lazy-init="false"
//这种情况下,意味着这里的不设置的情形就等同于lazy-init="false"的情形
//众所周知的东西,直接默认吧,别废话了,废话多了就外行了
<bean id="accountDao" class="com.wiley.beginningspring.ch2.~CAAccountDaoInMemoryImpl"
lazy-init="false">
</bean>
</beans>
该xml文件执行之后会怎样?
比如<bean>标签执行后会怎样?
理解初始化所必须知道的知识:
1 创建bean可以通过XML,当然也可以通过java(还是XML方便啊)
2 我们肯定最好把这些bean都先初始化出来,这样一来可以及早发现错误,但却消耗内存!(这一做法的学名叫预先初始化)
3 如果内存消耗真的很大,我们就换一种做法,不要先都初始化出来,到需要它的时候才初始化它(这一做法的学名叫延迟初始化)
4 beans中的default-lazy-init="true"实际上是将容器中的所有的bean的初始化创建都延迟了
5 bean中的lazy-init="false"实际上是对某个单独bean进行的设置,表示允许这个bean可以预先创建
4和5的做法其实就是,把所有人都关进黑监狱了,但是要允许每个犯人可以打开一扇窗户!!
上面是通过xml配置文件做到的延迟初始化!
我们可以换一种方式来做: 通过注解!!
这里必须要了解的知识:
1 首先,我做这样一件事:在applicationContext.xml文件中加一行代码:
<context:component-scan base-package="com.ect.somepackage"/>
这一行执行后会发生什么?
将自动扫描路径(base-package)下面的包(com.ect.somepackage),
如果
该包中的一个类带了@Service注解,
将该类的Bean自动注册到Spring容器,
这一做法等同于
在applicationContext.xml文件定义<bean>,
注解无非就是同一件事情另一种方式
xml中定义标签方式和这种方式做的完全是同一件事情
干同一件事情的两种方式的这种关系可以像下面这样理解:
方式一等同于方式二
把两种方式放在一起比较,就会更加清楚,这是一种很好的做法:
@Service("xxxDao")
//该注解做了什么呢?
1调用 xxxDaoImpl类的无参构造方法
2将该实例取名为xxxDao
3注入到spring容器中
4该实例称为bean
@Scope("prototype")
public class xxxDaoImpl implements xxxDao{
.....
}
相当于:
<bean id="xxxDao"
class="com.ect.somepackage.dao.xxxDaoImpl" scope="prototype">
......
</bean>
这个标签做的事情是:
1.调用类xxxDaoImpl无参构造方法
2.实例化xxxDaoImpl类,
3.将实例取名为xxxDao,这个实例注入到spring容器中,成为Bean
代码一:
@Service("accountService")
//这个service做了什么事情呢?
//注解的类是谁?AccountServiceImpl!
//所以做的事情就是:实例化该类获得一个实例,取名为accountService,注册到spring容器称为bean
@Lazy(true)
//先忽略注解,先了解这个类
//定义的类是AccountServiceImpl
//该类是一个实现的类
//实现的类是AccountService
//这两个类都要实例化么?肯定不能直接实例化接口类的,只能实例化接口类的实现类的
//怎么如何实例化呢?
public class AccountServiceImpl implements AccountService{
//...
}
这段代码等同于:
<beans xmlns="" xmlns:xsi="" xsi:schemaLocation="">
<bean id="accountService" class="com.wiley.beginningspring.ch2.~CAAccountServiceImpl"
lazy-init="true">
</bean>
</beans>
代码二:
@Configuration
//先忽略注解,看下面那个类
//类名很有意思看一哈:Ch2BeanConfiguration
//Ch2表示第二章,莫非还有第三章,第四章么?貌似啊
//BeanConfiguration表示bean配置(姑且叫bean工厂类)
//没有固化的思考,如同没根的枯草,一定会被吹得胡乱飞起!
public class Ch2BeanConfiguration{
@Bean
@Lazy(true)
//忽略注解,在该类中定义了一个accountServie方法
//注意返回值的类型:返回值的类型名称和方法名称相同
//这说明这是一个工厂方法
//工厂方法就是用来生产实例的
//现在进入方法中看哈逻辑
//工厂方法的逻辑很简单:就是调用类的构造方法然后将结果返回
//话句话说,我调用这个工厂方法实际上只做一件事情就是实例化啊
//到这里@Bean做了什么事情就很清楚了,
//1.调用accountService方法
2.将实例命名为accountService
3.将该实例注册到spring容器,从而成为bean
public AccountService accountService(){
//调用AccountServiceImpl类的构造方法
AccountServiceImpl bean = new AccountServiceImpl();
//返回方法调用的返回值
return bean;
//这里要注意的是:方法的返回值的类型是AccountService
//而构造方法的返回值的类型是AccountServiceImpl
//按理说,类型名已经冲突了,这他妈合法么?是不是写错了?
//如果没有写错的话
//我们将观察到一些重要的知识:
1 接口类肯定是不能new的
2 接口类的实现类是可以new一个实例的
3 接口类的实现类的实例将被视为该接口类的一个实例
4 接口只含有一些没有方法体的方法,像是一个标准,规范一样,new是new不了了
//人有时候就是这么简单,给他一个说法,他的内心世界就平静了
//说实在的,猜出知识是最简单的,前提是发生在这里的一切是真的
}
//....
}
那这段代码究竟表示什么意思呢?
既然是同一件事情的两种方式
那就换成另外一种方式表达吧
就是:
<beans xmlns="" xmlns:xsi="" xsi:schemaLocation="">
<bean id="accountService" class="com.wiley.beginningspring.ch2.~CAAccountServiceImpl"
lazy-init="true">
</bean>
</beans>
总结:代码一和代码二无非就是注解的两种方式而已!!