04-Spring-注解的IOC和DI
2020-12-30 本文已影响0人
XAbo
**Spring总结:1.通过IOC容器管理Bean。 2.通过DI管理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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--告知Spring Bean的创建配置在类中 新增context命名空间 -->
<context:component-scan base-package="com.annotation"></context:component-scan>
</beans>
AccountServicesImpl:
/*
XML的配置
<bean id="accountServices" class="com.annotation.services.AccountServicesImpl" scope="" init-method="" destory-method="">
<property name="" value=""></property>
<property name="" ref=""> </property>
</bean>
--1 xml实现的功能:
1.用于管理对象:1.1 bean标签创建对象; 1.2 init-method destory-method;管理bean的生命周期 ; 1.3 scope:管理bean的作用范围。
2.用于注入数据:property。
--2 注解实现的功能:
1.用于管理对象:
1.1 @Component创建对象,将当前对象存入IOC容器 ,其属性value用于指定bean的id,默认是当前类名(首字母小写)。
1.2 @Controller:表现层 @Service:业务/服务层 @Repository:持久层 这三个注解的作用和属性跟@Component一样。
2.用于注入数据的(JavaBean类型)
2.1 @Autowired:按照类型注入,Bean对象类型和要注入的变量类型匹配。
2.1.1 注入不依赖构造方法或set方法,Spring直接在IOC容器中找到“合适”的一个对象,将其属性注入。
2.1.2 当IOC容器中有多个匹配到的话,在根据变量名称进行匹配。
2.2 @Qualifier:按照类型基础之上再按照名称注入,value属性指定Bean的ID。
2.2.1 给类成员注入时不能单独使用,需要跟Autowired配合使用。
2.2.2 给方法参数注入时可以。
2.3 @Resource:直接按照Bean的id注入,可独立使用。使用name来指定Bean的id。
3. 用于注入数据的(基本和String类型)
3.1 @Value:使用value属性指定要注入的值,可使用spEL。${表达式}
4. 用于注入数据的:集合类型的属性只能通过XML进行注入。
5. 管理Bean的作用范围:@Scope指定bean的作用范围,属性value指定范围的取值。
6. 管理Bean的生命周期:@PreDestory :用于指定销毁方法。 @PostConstruct :用于指定初始化方法。
补充:@Autowired注解位置:
1.放置在对应成员变量的set方法上.[弱依赖,可有可无,不影响整个类]
2.放置在成员变量上,Spring通过反射直接对成员变量进行注入(推荐)[有缺点,idea还会警告:不建议使用这种方式注入]
3.放在构造器上[强制依赖]
*/
@Component(value = "accountServices")
public class AccountServicesImpl implements AccountServices {
//@Autowired
@Resource
private AccountDao accountDao;
public void saveAccount() {
accountDao.saveAccount();
}
}
注解的Autowired方式
AccountDaoImpl:
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
@Override
public void saveAccount() {
System.out.println("DAO---保存账户数据");
}
}
客户端:
public class client {
public static void main(String[] args) {
ClassPathXmlApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
accountServices.saveAccount();
}
}
二、依赖第三方jar
1.当依赖第三方jar包的时候,不能使用注解的时候,如何去掉剩余标签?
<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
-->
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--告知Spring Bean的创建配置在类中 新增context命名空间 -->
<context:component-scan base-package="com.annotation"></context:component-scan>
<!--这些bean不能使用注解写在源码上-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSourrce">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb"></property>
<property name="user" value="root"></property>
<property name="password" value="213"></property>
</bean>
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
</beans>
2.使用新注解解决bean配置文件中遗留的便签。
使用SpringConfig类:
/*
* @Configuration:指定当前类是一个配置类.
* @ComponentScan:通过注解指定spring在创建容器时候要扫码的包。等同于:<context:component-scan base-package="com.annotation"></context:component-scan>
* @Bean:把当前方法的返回值放入SpringIOC容器中。属性:name指定bean的id,默认是当前方法名。其装配bean的方式与@Autowired相似。
@PropertySource指定加载的properties配置文件。classpath表示类路径。
* */
@Configuration
@ComponentScan(basePackages = "com.annotation")
//@Import("otherConfig.class") 可导入其他配置子类。
/*@Import相当于xml文件中的
* <import resource="classpath*:/spring/job-timer.xml" />
*/
@PropertySource("classpath:db.properties")
public class SpringConfig {
@Valure("$jdbc.driver")
private String driver;
@Valure("$jdbc.url")
private String url;
@Valure("$jdbc.user")
private String user;
@Valure("$jdbc.pwd")
private String passWrod ;
@Bean(name="dataSource")
public DataSource createDataSource(){
ComboPooledDataSourrce ds = new ComboPooledDataSourrce()
//ds.setDriverClass("com.mysql.jdbc.Driver");
//ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
//ds.setUser("root");
//ds.setPassword("123");
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(user);
ds.setPassword(passWrod);
return ds;
}
@Bean(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
}
用到的db.properties配置文件
#mysql jdbc
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.user=root
jdbc.pwd=123
3.此时不需要bean配置文件。
三、集成junit
1.传统的测试用例
import com.annotation.services.AccountServices;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AccountServiceTest {
@Test
public void testFindAll() {
ClassPathXmlApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
List<Account> accounts = accountServices.findAll();
for (Account account : accounts) {
System.out.println(account);
}
}
@Test
public void testFindOne() {
ClassPathXmlApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
Account accounts = accountServices.findOne("xzb");
System.out.println(account);
}
}
2.Spring集成junit
import com.annotation.services.AccountServices;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/*
* Spring整合junit
* 1.导入spring整合junit的jar
* 2.@RunWith,使用junit提供一个注解把原有的main方法替代了,换成spring提供的。
* 3.@ContextConfiguration 告知spring的运行器,spring的IOC容器创建是xml还是注解。Spring 5.x <---> junit 4.12+
* location:指定XML文件的位置,加上classpath,表示在类路径下。
* classes:指定注解所在位置。
*/
@RunWith(SpringJUnit4ClassRunner.class)//指定main
@ContextConfiguration(SpringConfig.class)//获取Sping IOC容器
//@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
@Autowired
private AccountServices accountServices = null;
@Test
public void testFindAll() {
List<Account> accounts = accountServices.findAll();
for (Account account : accounts) {
System.out.println(account);
}
}
@Test
public void testFindOne() {
Account accounts = accountServices.findOne("xzb");
System.out.println(account);
}
}
junit为什么不采用配置到 xml 中的方式呢?
第一:当我们在 xml 中配置了一个 bean, spring 加载配置文件创建容器时,就会创建对象。
第二:测试类只是我们在测试功能时使用,而在项目中它并不参与程序逻辑,也不会解决需求上的问
题,所以创建完了,并没有使用。那么存在容器中就会造成资源的浪费。