一.基于注解的IOC与DI实现
1.注意事项:
使用注解注入时,不需要set方法;
基于注解整合时,导入约束时需要多导入一个 context 名称空间下的约束。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
2.使用@Component 注解配置管理的资源
@Component("accountService") public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao; public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } } @Component("accountDao") public class AccountDaoImpl implements IAccountDao { private DBAssit dbAssit; }
3.在bean.xml中进行配置
<!-- 告知 spring 创建容器时要扫描的包 --> <context:component-scan base-package="com.itheima"></context:component-scan> <!-- 配置 dbAssit --> <bean id="dbAssit" class="com.itheima.dbassit.DBAssit"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///spring_day02"></property> <property name="user" value="root"></property> <property name="password" value="1234"></property> </bean>
4.常用注解
(1)@Component:相当于bean
(2)@Controller:表现层bean
@Service:业务层bean
@Repository:持久层bean
(3)@Autowired:自动根据变量类型注入,先在容器中查该类,如没有则报错;如果有多个该类型对象,则根据对象名查找注入,如果没有相应对象名则报错。它只能注入其他 bean 类型;
自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他 bean 类型。当有多个 类型匹配时,使用要注入的对象变量名称作为 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到 就报错。
(4)@Qualifier:作用: 在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和 @Autowire 一起使用;但是给方法参数注入时,可以独立使用。 属性: value:指定 bean 的 id。
(5)@Resource:作用: 直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。 属性: name:指定 bean 的 id。
(6)@Value:作用: 注入基本数据类型和 String 类型数据的 属性: value:用于指定值
(7)除了@Value,其他只能注入bean类型
(8)@Scope:作用: 指定 bean 的作用范围。 属性: value:指定范围的值。 取值:singleton prototype request session globalsession
(9)@PostConstruct 作用: 用于指定初始化方法。
(10) @PreDestroy 作用: 用于指定销毁方法。
5.新注解(将bean.xml中的其他配置转换为配置类)
(1)@Configuration
作用: 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用 AnnotationApplicationContext(有@Configuration 注解的类.class)。 属性: value:用于指定配置类的字节码
已经把配置文件(bean.xml)用类(SpringConfigration)来代替了
@Configuration public class SpringConfiguration { }
(2) @ComponentScan
作用: 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的: <context:component-scan base-package="com.itheima"/>是一样的。 属性: basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
@Configuration @ComponentScan("com.itheima") public class SpringConfiguration { }
已经配置好了要扫描的包
(3) @Bean
作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。 属性: name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
/** * 连接数据库的配置类 */ public class JdbcConfig { /** * 创建一个数据源,并存入 spring 容器中 * @return */ @Bean(name = "dataSource") public DataSource createDataSource() { try { ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setUser("root"); ds.setPassword("1234"); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql:///spring_day02"); return ds; } catch (Exception e) { throw new RuntimeException(e); } } /** * 创建一个 DBAssit,并且也存入 spring 容器中 * @param dataSource * @return */ @Bean(name = "dbAssit") public DBAssit createDBAssit(DataSource dataSource) { return new DBAssit(dataSource); } }
已经把数据源和 DBAssit 从配置文件中移除了,此时可以删除 bean.xml 了。
(4)由于没有了配置文件,创建数据源的配置又都写死在类中了。如何把它们配置出来呢
@PropertySource 用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。 属性: value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 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; /** * 创建一个数据源,并存入 spring 容器中 * @return */ @Bean(name = "dataSource") public DataSource createDataSource() { try { ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setDriverClass(driver); ds.setJdbcUrl(url); ds.setUser(username); ds.setPassword(password); return ds; } catch (Exception e) { throw new RuntimeException(e); } } }
(5)已经有了两个配置类,但是他们还没有关系。如何建立他们的关系呢?
@Import
作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问 题。 属性: value[]:用于指定其他配置类的字节码。
@Configuration @ComponentScan(basePackages = "com.itheima.spring") @Import({JdbcConfig.class}) public class SpringConfiguration { } @Configuration @PropertySource("classpath:jdbc.properties") public class JdbcConfig { }
(6)由于没有配置文件了,如何获取容器呢?
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
二.JUnit与注解配置:
*目的:能不能测试时直接就编写测试方法,而不需要手动编码来获取容器呢
public class AccountServiceTest { private ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); private IAccountService as = ac.getBean("accountService", IAccountService.class); }
(1)导包
(2)用@RunWith替换使用的运行器
@RunWith(SpringJUnit4ClassRunner.class) public class AccountServiceTest { }
(3)使用@ContextConfiguration 指定 spring 配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations= {"classpath:bean.xml"}) public class AccountServiceTest { }
@ContextConfiguration 注解: locations 属性:用于指定配置文件的位置。如果是类路径下,需要用 classpath:表明 classes 属性:用于指定注解的类。当不使用 xml 配置时,需要用此属性指定注解类的位置。
(4)使用@Autowired 给测试类中的变量注入数据
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:bean.xml"}) public class AccountServiceTest { @Autowired private IAccountService as; }