(一)xml与注解相结合模式
1)实际企业开发中,纯xml模式使⽤已经很少了,一般是xml和注解相结合或者是纯注解方式。
2)引入注解功能,不需要引入额外的jar。
3)xml+注解结合模式,xml⽂件依然存在,所以,spring IOC容器的启动仍然从加载xml开始。
4)第三方jar中的bean定义在xml,比如德鲁伊数据库连接池,自己开发的bean定义使用注解。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
">
<!--1.加载context命名空间的支持-->
<!-- xmlns:context="http://www.springframework.org/schema/context"-->
<!--开启注解扫描,并配置扫描的包路径-->
<context:component-scan base-package="com.nanmao"/>
<!--导入外部配置文件,jdbc.properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.userName}"/>
<property name="password" value="${jdbc.passWord}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="maxWait" value="${jdbc.maxWait}"/>
</bean>
<!--可以通过import标签在此配置文件中导入其他配置文件-->
<import resource="applicationContext-other.xml"/>
</beans>
可以将相关配置参数定义到配置文件jdbc.properties中,然后通过${key}的方式进行导入。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bank?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
jdbc.userName=root
jdbc.passWord=root
jdbc.initialSize=5
jdbc.maxActive=10
jdbc.maxWait=3000
xml中标签与注解的对应(IoC)
xml形式 | 对应的注解形式 |
---|---|
bean标签 | @Component(“accountDao”),一般用于一些组件命名。针对分层代码开发提供了@Component的三种别名@Controller、@Service、@Repository分别⽤于控制层类、服务层类、dao层类的bean定义,这四个注解的⽤法完全⼀样,只是为了更清晰的区分⽽已 |
scope属性 | @Scope(“prototype”),默认单例,注解加在类上 |
init-method属性 | @PostConstruct,注解加在⽅法上,该⽅法就是初始化后调⽤的⽅法 |
destory-method属性 | @PreDestory,注解加在⽅法上,该⽅法就是销毁前调⽤的⽅法 |
@Component("userService")
@Scope
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
public UserServiceImpl(){
System.out.println("service is running...");
}
@PostConstruct
public void init(){
System.out.println("init.....");
}
@PreDestroy
public void destroy(){
System.out.println("destroy.....");
}
@Override
public void save() {
System.out.println("userService impl running");
userDao.save();
}
}
DI 依赖注入的注解实现方式
@Autowired(推荐使⽤)
@Autowired为Spring提供的,需要导入org.springframework.beans.factory.annotation.Autowired。在spring-beans jar包中已导入。
@Autowired采取的策略为按照类型注⼊。比如下图中的AccountDao:该注解会去spring容器中找到类型为AccountDao的类,然后将其注⼊进来。这样会产生⼀个问题,当⼀个类型有多个bean值的时候,会造成⽆法选择具体注⼊哪⼀个的情况,这个时候我们需要配合着@Qualifier使⽤。@Qualifier告诉Spring具体去装配哪个对象。
@Service("transferService")
@Scope
public class TransferServiceImpl implements TransferService {
@Autowired //按类型查找
@Qualifier("accountDao") //AccountDao下如果有多个实现类,可以用@Qualifier("beanId")区分
private AccountDao accountDao;
@Resource
@Resource 注解由 J2EE 提供,需要导入包 javax.annotation.Resource。
@Resource 默认按照 ByName ⾃动注入。如果同时指定了 name 和 type,则从Spring上下文中找到唯⼀匹配的bean进行套装配,找不到则抛出异常。如果指定了 name,则从上下⽂中查找名称(id)匹配的bean进行装配,找不到则抛出异常。如果指定了 type,则从上下⽂中找到类似匹配的唯⼀bean进⾏装配,找不到或是找到多个,都会抛出异常。如果既没有指定name,⼜没有指定type,则自动按照byName方式进行装配;
注意:
@Resource 在 Jdk 11中已经移除,如果要使用,需要单独引入jar包
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
(二)纯注解模式
通过注解导入第三方bean
对应注解
@PropertySource,引⼊外部属性配置⽂件
@Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息
@Bean 将⽅法返回对象加⼊ SpringIOC 容器
@Import 引⼊其他配置类
@PropertySource(value = {"classpath:jdbc.properties"},ignoreResourceNotFound = true)
//注解导入配置文件的方式不支持classpath:* 我们可以写成数组的形式
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;
@Value("${jdbc.initialSize}")
private String initialSize;
@Value("${jdbc.maxActive}")
private String maxActive;
@Value("${jdbc.maxWait}")
private String maxWait;
@Bean("dataSource")
public DruidDataSource getDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(passWord);
dataSource.setInitialSize(Integer.parseInt(initialSize));
dataSource.setMaxActive(Integer.parseInt(maxActive));
dataSource.setMaxWait(Long.parseLong(maxWait));
return dataSource;
}
}
设置入口配置类
对应注解
@Configuration 表明这是一个配置类,表明程序入口
@ComponentScan 设置注解扫描包的位置
@Import 引⼊其他配置类
@Configuration
@ComponentScan("com.nanmao")
@Import({JdbcConfig.class})
public class SpringConfig {
}
启动容器:
Java SE模式下:
public class IocXmlTest {
@Test
public void TestIocContainer() {
//注解模式下通过AnnotationConfigApplicationContext来启动容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
System.out.println(accountDao);
}
}
Java WEB模式下:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--告诉contextLoaderListener我们使用的注解方式启动容器-->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<!--配置启动类的全限定名-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.nanmao.config.SpringConfig</param-value>
</context-param>
<!--使⽤监听器启动Spring的IOC容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
扩展注解:
@DependsOn(“beanId”) 控制bean的加载顺序,使其在指定bean加载完成后再加载
@Order(“1”) 配置类注解,控制配置类的加载顺序,多个配置类出现后,可以优先加载系统级的,然后加载业务级的