Spring IOC 学习笔记
Bean
<bean id="" class=""></bean> 注册
别人写的类已经写好了,没有注解,所有要bean来注册,注入IOC。
set 注入
set注入和getBean 注入,本质上没有区别。
set 注入
private DataSource dataSource;
public void setDataSource(DataSource ds){
this.dataSource = ds;
}
从 Spring getBean
@Autowired 注解原理是如何实现
@Autowired:
1.getBean(数据类型)
2.绑定到某个成员变量
@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。
@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
@Autowired
private AccountDao accountDao;
//@Autowired 通过反射的方式把account创建出来 AccountDao accountDao=getBean(AccountDao.calss)
@Override
public List<Account> selectAll() {
return accountDao.selectAll();
}
@Autowired 根据bean 类型从spring 上线文中进行查找,注册类型必须唯一,否则报异常。与@Resource 的区别在于,@Resource 允许通过bean 名称或bean 类型两种方式进行查找@Autowired(required=false) 表示,如果spring 上下文中没有找到该类型的bean 时, 才会使用new SoftPMServiceImpl();
<bean id="zoo" class="com.spring.model.Zoo" />
<bean id="tiger" class="com.spring.model.Tiger" />
<bean id="monkey" class="com.spring.model.Monkey" />
@Qualifier(指定注入Bean的名称)
如果容器中有一个以上匹配的Bean,则可以通过@Qualifier注解限定Bean的名称
作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用(可以跟Autowired搭配之用)。但是在给方法参数注入时可以。
属性:value:用于指定注入bean的id。
@Qualifier 和@AutoWired联合使用,自动装配的策略就变成byName
使用@Autowired 时,如果找到多个同一类型的bean,则会抛异常,此时可以使用 @Qualifier("beanName"),明确指定bean的名称进行注入,此时与 @Resource指定name属性作用相同。
@Qualifier(value = "限定标识符") // 字段、方法、参数
(1)XML配置中的<qualifier>标签指定的名字进行注入
<qualifier type="org.springframework.beans.factory.annotation.Qualifier" value="限定标识符"/>
其中type属性可选,指定类型,默认就是Qualifier注解类,name就是给Bean候选者指定限定标识符,一个Bean定义中只允许指定类型不同的<qualifier>,如果有多个相同type后面指定的将覆盖前面的。
@Autowired
//根据<qualifier>标签指定Bean限定标识符
public void initDataSource(@Qualifier("mysqlDataSource") DataSource dataSource) {
this.dataSource = dataSource;
}
使用@Qualifier("mysqlDataSource")来指定候选Bean的限定标识符,我们需要在配置文件中使用<qualifier>标签来指定候选Bean的限定标识符“mysqlDataSource”:
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<qualifier value="mysqlDataSource"/>
</bean>
(2)缺省的根据Bean名字注入 :最基本方式,是在Bean上没有指定<qualifier>标签时一种容错机制,即缺省情况下使用Bean标识符注入,但如果你指定了<qualifier>标签将不会发生容错。
@Autowired
@Qualifier(value = "mysqlDataSource2") //指定Bean限定标识符
//@Qualifier(value = "mysqlDataSourceBean")
//是错误的注入,不会发生回退容错,因为你指定了<qualifier>
public void initDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
(3)扩展@Qualifier限定描述符注解: 对@Qualifier的扩展来提供细粒度选择候选者;
如果我们有两个数据源,分别为Mysql和Oracle,因此注入两者相关资源时就牵扯到数据库相关,如在DAO层注入SessionFactory时,当然可以采用前边介绍的方式,但为了简单和直观我们希望采用自定义注解方式。
1.扩展@Qualifier限定描述符注解来分别表示Mysql和Oracle数据源
/** 表示注入Mysql相关 */
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Mysql {
}
@Autowired
public void initDataSource(@Mysql DataSource mysqlDataSource) {
this.mysqlDataSource = mysqlDataSource;
}
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<qualifier value="mysqlDataSource"/>
<qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
</bean>
Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());
2.扩展参数的注解
package cn.javass.spring.chapter12.qualifier;
public enum DataBase {
MYSQL;
}
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface DataSourceType {
String ip(); //指定ip,用于多数据源情况
DataBase database();//指定数据库类型
}
@Autowired
public void initDataSource(
@DataSourceType(ip="localhost", database=DataBase.MYSQL)
DataSource mysqlDataSource,
this.mysqlDataSource = mysqlDataSource;
}
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<qualifier value="mysqlDataSource"/>
<qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
<qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">
<attribute key="ip" value="localhost"/>
<attribute key="database" value="MYSQL"/>
</qualifier>
</bean>
Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());
@Resource 注解的工作原理
@Resource注解与@Autowired注解作用非常相似
@Resource等价于 getBean
@Resource:
1.getBean(id)
2.绑定到某个成员变量
作用:直接按照bean的id注入,它可以独立使用。
属性:name:用于指定bean的id。
要为该属性赋值或注入时需要到这个注解
@Resource(name="xxx"),相当于为该属性注入一个名称为"xxx"的<bean>。
<bean id="accountDao" class="com.chen.dao.AccountDao"></bean>
这是详细一些的用法,说一下@Resource的装配顺序:
(1)、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
(2)、指定了name或者type则根据指定的类型去匹配bean
(3)、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错
然后,区分一下@Autowired和@Resource两个注解的区别:
(1)、@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配
(2)、@Autowired是Spring的注解,@Resource是J2EE的注解,这个看一下导入注解的时候这两个注解的包名就一清二楚了
Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。
< property name=“name” value=“奔驰500” />
三层架构
SpringMVC IOC 容器
Spring IOC 容器 Service 和 Dao
注入方式-1 构造方法注入
使用构造函数完成依赖注入的实例
@Component 注解的原理
<context:component-scan base-package="com.chen.dao,com.chen.service" />
作用:
1.默认单例
2.Component:把该类通过反射Class.forName() 获取类对象,通过类对象 .newInstance 创建实例,保存在 IOC 容器,默认 id 就算类名称(包名,类名)
通用注解
和它功能相同的还有
- Controller: 一般用在表现层 (Spring IOC 容器)
- Service: 一般用在业务层 (Spring IOC 容器)
- Respository: 一般用在持久层 (Spring IOC 容器)
注意-扫描包的范围
SpringMVC 扫描配置
<context:component-scan base-package="cn.lusq.controller"></context>
@Repository
@Repository 给Dao层用的
标记数据持久化
创建bean 放到容器里头
@Repository("accountDao") 等同于 <bean id="accountDao" class="com.chen.dao.IAccountDaoImpl"></bean>
//@Repository("accountDao") 等同于 <bean id="accountDao" class="com.chen.dao.IAccountDaoImpl"></bean>
@Repository("accountDao")
public class IAccountDaoImpl implements IAccountDao {
@Override
public void saveAccount(Account account) {
System.out.println("Dao:保存了"+account);
}
}
@Component
@Component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class="">)
@Component 是 @Repository 的元注解
@Component 是 @Service 的元注解
@Service
@Service 是给服务层用的
标记业务处理
作用:
@Service注解用于类上,标记当前类是一个service类,加上该注解会将当前类自动注入到spring容器中,不需要再在applicationContext.xml文件定义bean了。
1、 其getBean的默认名称是类名(头字母小写),可以@Service(“xxxx”)这样来指定。
2、其定义的bean默认是单例的,可以使用@Service(“beanName”) @Scope(“prototype”)来改变。
3、可以通过@PostConstruct和@PreDestroy指定初始化方法和销毁方法(方法名任意)。
@Controller
@controller 控制器(注入服务)
用来标记后端控制器
总结:
1.<bean id="" class="" />
2.@component @Service @Respository @Controller
3.解决如何让IOC创建一个单例对象,并且放在IOC容器,等待getBean 或 @Resource @Autowired 来获取它
控制反转
1.注册BookDaoImpl到IOC容器
1.注解 @Component (@Respository,@Service,@Controller)
2.<bean id="" class=""></bean>
2.getBean
1.byName(id) @Resource
2.byType @Autowired
SpringIOC 基本思想
1.除了 实体类,工具类以外,其他想办法放到IOC容器里面
-注解 @Component
-<bean id="" class=""></bean>
2.getBean
@Autowired
@Resource
@Autowired+@Qualifier == @Resource