spring框架史上最全深入理解( 二 )

基于注解的注入:
bean的一个属性autowire , autowire主要有三个属性值:constructor , byName , byType 。
constructor:通过构造方法进行自动注入 , spring会匹配与构造方法参数类型一致的bean进行注入 , 如果有一个多参数的构造方法 , 一个只有一个参数的构造方法 , 在容器中查找到多个匹配多参数构造方法的bean , 那么spring会优先将bean注入到多参数的构造方法中 。
byName:被注入bean的id名必须与set方法后半截匹配 , 并且id名称的第一个单词首字母必须小写 , 这一点与手动set注入有点不同 。
byType:查找所有的set方法 , 将符合符合参数类型的bean注入 。
注解方式注册bean , 注入依赖
主要有四种注解可以注册bean , 每种注解可以任意使用 , 只是语义上有所差异:
@Component:可以用于注册所有bean
@Repository:主要用于注册dao层的bean
@Controller:主要用于注册控制层的bean
@Service:主要用于注册服务层的bean
描述依赖关系主要有两种:1.@Resource
2.@Autowired
@Resource java的注解 , 默认以byName的方式去匹配与属性名相同的bean的id , 如果没有找到就会以byType的方式查找 , 如果byType查找到多个的话 , 使用@Qualifier注解(spring注解)指定某个具体名称的bean 。
@Resource@Qualifier("userDaoMyBatis")private IUserDao userDao;public UserService(){}@Autowired:spring注解 , 默认是以byType的方式去匹配类型相同的bean , 如果只匹配到一个 , 那么就直接注入该bean , 无论要注入的 bean 的 name 是什么;如果匹配到多个 , 就会调用 DefaultListableBeanFactory 的 determineAutowireCandidate 方法来决定具体注入哪个bean 。determineAutowireCandidate 方法的内容如下:
determineAutowireCandidate 方法的逻辑是:
先找 Bean 上有@Primary 注解的 , 有则直接返回 bean 的 name 。
再找 Bean 上有 @Order , @PriorityOrder 注解的 , 有则返回 bean 的 name 。
最后再以名称匹配(ByName)的方式去查找相匹配的 bean 。
可以简单的理解为先以 ByType 的方式去匹配 , 如果匹配到了多个再以 ByName 的方式去匹配 , 找到了对应的 bean 就去注入 , 没找到就抛出异常 。
还有一点要注意:如果使用了 @Qualifier 注解 , 那么当自动装配匹配到多个 bean 的时候就不会进入 determineAutowireCandidate 方法(亲测) , 而是直接查找与 @Qualifer 指定的 bean name 相同的 bean 去注入 , 找到了就直接注入 , 没有找到则抛出异常 。
tips:大家如果认真思考可能会发现 ByName 的注入方式和 @Qualifier 有点类似 , 都是在自动装配匹配到多个 bean 的时候 , 指定一个具体的 bean , 那它们有什么不同呢?
ByName 的方式需要遍历 , @Qualifier 直接一次定位 。在匹配到多个 bean 的情况下 , 使用 @Qualifier 来指明具体装配的 bean 效率会更高一下 。
spring 支持三种创建bean1.调用构造器创建bean;
2.调用静态工厂方法创建bean;
3.调用实例工厂方法创建bean;
ioc底层原理:dom4j+反射
反射一定会走无参构造函数;
反射原理 加载配置xml配置文件 , 解析xml文件 , bean的几点 ,  初始化bean id class=是全路径;
拿到beanid 去容器中
spring容器的 bean的作用域:1.singleton:这种bean范围是默认的 , 这种范围确保不管接受到多少个请求 , 每个容器中只有一个bean的实例 , 单例的模式由bean factory自身来维护;
2.prototype:原型范围与单例范围相反 , 为每一个bean请求提供一个实例;
3.request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例 , 在请求完成以后 , bean会消失并被垃圾回收;
4.session:与请求范围类似 , 确保每一个session中有一个bean的实例 , 在session过期后 , bean会随之失效;
5.global_session: global_session 和portlet应用相关 , 当你的应用部署在portlet容器中工作时 , 他包含很多portlet , 如果你想要声明让所有的portlet公用全局的存储的话 , 那么这全局变量需要存储在global_session中 。
springmvc 和 struts2比较


推荐阅读