文章目录
- 一、说明
- 二、用于创建对象的
- 2.1、Component注解
- 2.1.1、定义Bean
- 2.1.2、主配置文件配置扫描注解
- 2.1.3、测试
- 2.1.4、Component注解总结
- 2.2、Controller注解
- 2.3、Service注解
- 2.4、Repository注解
- 三、用于注入数据的
- 3.1、Autowired注解
- 3.1.1、定义Bean
- 3.1.2、主配置文件配置扫描注解
- 3.1.3、测试
- 3.1.4、改造
- 3.1.5、总结
- 3.2、Qualifier注解
- 3.2.1、定义Bean
- 3.2.2、总结
- 3.3、Resource注解
- 3.3.1、定义Bean
- 3.3.2、总结
- 3.4、Value注解
- 3.4.1、案例1
- 3.4.1.1、定义Bean
- 3.4.1.2、测试
- 3.4.2、案例2
- 3.4.2.1、创建db.properties文件
- 3.4.2.2、主配置文件需要将properties文件引入进来
- 3.4.2.3、定义Bean
- 3.4.2.4、测试
- 3.4.3、总结
- 3.5、大总结
- 四、用于改变Bean的作用域的
- 4.1、定义Bean
- 4.2、测试
- 4.3、总结
- 五、和Bean的生命周期相关的
- 5.1、定义Bean
- 5.2、测试
- 5.3、总结
一、说明
回顾一下基于xml配置的Spring对Bean的管理 ,对Bean的完整管理如下所示:
<bean id="" class="" init-method="" destroy-method="" scope=""><property name="" value=""/><property name="" ref=""/>
</bean>
分析可以发现:我们对Bean的管理就四个方面,分别是:
- 用于创建对象的
- 用于注入数据的
- 用于改变Bean的作用域的
- 和Bean的生命周期相关的
其实对于注解来说,也是包括了这四个方面,换句话说,使用注解的方式管理Bean和使用xml的方式管理Bean作用是完全一样的,区别仅仅在于配置的形式不同而已。
二、用于创建对象的
2.1、Component注解
2.1.1、定义Bean
@Component
public class DogService {}
2.1.2、主配置文件配置扫描注解
<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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><!-- 告诉spring在创建容器时要扫描的包 --><context:component-scan base-package="cn.bdqn"/></beans>
2.1.3、测试
@Test
public void testDogServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");DogServiceImpl dogService = (DogServiceImpl) ac.getBean("dogServiceImpl");System.out.println(dogService);
}
2.1.4、Component注解总结
-
作用
用于把对当前修饰的类创建出来,并存放到Spring容器中。
-
属性
a. 用该注解所创建的对象默认的id名称是当前类名,且首字母改小写
b. 可以通过value属性手动的指定bean的id。
2.2、Controller注解
一般用在表现层,例如SpringMVC、Struts2
2.3、Service注解
一般用在业务层,例如Service层
2.4、Repository注解
一般用在持久层7.2.5、总结
- Controller、Service、Repository这三个注解他们的作用和属性与Component是一模一样。
- 既然一模一样,之所以Spring框架还要提供,主要是Spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰。
- 他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的
三、用于注入数据的
3.1、Autowired注解
作用:
自动按照类型注入。
3.1.1、定义Bean
// 用户service接口
public interface UserService {public void printUserDao();
}
// 用户service接口实现,bean的名称改为:userService
@Service("userService")
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;// 打印UserDao,看是否可以将值打印出来,如果打印出来说明值真的注入成功了public void printUserDao(){System.out.println(userDao);}
}
// 用户UserDao接口
public interface UserDao {}
// 用户UserDao接口实现,bean的名称改为:userDao01
@Repository("userDao01")
public class UserDaoImpl01 implements UserDao {}
3.1.2、主配置文件配置扫描注解
<beans><!-- 告诉spring在创建容器时要扫描的包 --><context:component-scan base-package="cn.bdqn"/>
</beans>
3.1.3、测试
@Test
public void testUserServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService) ac.getBean("userService");userService.printUserDao(); // cn.bdqn.dao.impl.UserDaoImpl@7a52f2a2
}
3.1.4、改造
假设系统中存在两个UserDao的实现,现在再添加一个。现在再添加测试:
@Repository("userDao02")
public class UserDaoImpl02 implements UserDao {}
再次运行程序,会发现,程序报错:
No qualifying bean of type 'cn.bdqn.dao.UserDao' available: expected single matching bean but found 2: userDao01,userDao02
翻译:没有找到一个可用的UserDao,期望能够匹配一个,但是发现了2个。换句话说,由于是根据类型匹配的,而userDao01,userDao02都是符合注入的类型的,不知道要用哪个了.
该如何解决呢?既然Spring不知道具体要用哪个了,那我们由开发者来去指定其中的一个告诉Spring你就用这个注入就可以了,那么实现方式就是:通过名称告诉即可
解决方案:
@Service("userService")
public class UserServiceImpl implements UserService {// 将变量的名称修改为userDao01,那么依赖注入的时候就使用UserDaoImpl01@Autowiredprivate UserDao userDao01;
}
再次测试,程序正常执行。
3.1.5、总结
- 该注解是根据类型自动注入,假如只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
- 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
- 如果容器中有多个bean对象类型和要注入的变量类型匹配,则可能会发生错误,解决办法就是修改变量的名称为其中的某一个bean的名称
3.2、Qualifier注解
在7.3.1章节使用Autowired注解的时候,会存在一个问题,就是如果系统中存在多个类型的Bean都匹配的时候,就会找不到到底要使用哪个Bean对象了,会报错,我们采取的解决办法是:修改变量名即可解决 , 但是这种做法实际上是挺菜的,我现在就想使用userDao这个变量名,那么能否有一种更好的解决办法呢?答案是肯定的,即使用Qualifier注解。
3.2.1、定义Bean
Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean,修改如下:
public class UserServiceImpl implements UserService {@Autowired@Qualifier(value = "userDao01") // 通过此注解中的value属性明确指定要用哪个name的beanprivate UserDao userDao;
}
3.2.2、总结
- 在按照类型注入的基础之上再按照名称注入,它在给类的成员变量注入时不能单独使用,需要搭配Autowired注解。
3.3、Resource注解
3.3.1、定义Bean
Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean,修改如下:
@Service("userService")
public class UserServiceImpl implements UserService {@Resource(name = "userDao01")private UserDao userDao;
}
3.3.2、总结
- 该注解采用的是直接按照bean的id注入,它可以独立使用,name用于指定bean的id。
注意:
使用Autowired、Qualifier以及Resource这三个注解都只能注入其他bean类型的数据,对于基本数据类型和String类型是无法通过使用该3个注解实现。同时,对于集合数据类型的注入只能通过XML来实现。
3.4、Value注解
作用:
用于注入基本类型和String类型的数据。
3.4.1、案例1
3.4.1.1、定义Bean
@Component("jdbcUtils")
public class JdbcUtils {@Value("com.mysql.jdbc.Driver")private String driverClass;
}
3.4.1.2、测试
@Test
public void testJdbcUtils() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");JdbcUtils utils = (JdbcUtils) ac.getBean("jdbcUtils");System.out.println(utils); // com.mysql.jdbc.Driver
}
3.4.2、案例2
如果Value注解用于案例1,那这样太菜了,我们要为driverClass这个变量赋值,那岂不是直接赋值得了,还需要搞一个Value直接赋值吗?显然是没有必要的,所以一般来说,Value注解常用于对配置文件内容的读取。
3.4.2.1、创建db.properties文件
driverClass=com.mysql.jdbc.Driver
port=3306
3.4.2.2、主配置文件需要将properties文件引入进来
<beans><!-- 告诉spring在创建容器时要扫描的包 --><context:component-scan base-package="cn.bdqn"/><!-- 将properties文件引入到Spring框架中--><context:property-placeholder location="classpath:db.properties"/>
</beans>
3.4.2.3、定义Bean
@Component("jdbcUtils")
public class JdbcUtils {@Value("${driverClass}")private String driverClass;@Value("${port}")private Integer port;
}
3.4.2.4、测试
@Test
public void testJdbcUtils() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");JdbcUtils utils = (JdbcUtils) ac.getBean("jdbcUtils");System.out.println(utils); // com.mysql.jdbc.Driver,3306
}
3.4.3、总结
该注解通过可以实现对基本数据类型和String类型的注入,并且是支持使用Spring的EL表达式。那么对于Spring的EL表达式的语法就是:${表达式}。
3.5、大总结
以上注解的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的
四、用于改变Bean的作用域的
方式:
- 使用Scope注解,作用是用于指定bean的作用范围。该注解有一个value属性,可以指定范围的取值,常用取值:singleton、 prototype
- 该Scope注解默认的value值就是单例的【singleton】
4.1、定义Bean
Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean修改作用域,修改如下:
@Service("userService")
@Scope("singleton")
public class UserServiceImpl implements UserService{}
4.2、测试
@Test
public void testUserServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");UserService userService = (UserService) ac.getBean("userService");UserService userService2 = (UserService) ac.getBean("userService");System.out.println(userService == userService2); // true
}
改造一下:如果将上例的UserServiceImpl中的Scope改为prototype,则再次测试的时候会返回false。
4.3、总结
Scope该注解的作用就和在bean标签中使用scope属性实现的功能是一样的
五、和Bean的生命周期相关的
5.1、定义Bean
Bean的定义,仍然采用7.3.1章节所定义好的Bean,唯一的区别是UserServiceImpl这个Bean添加了一个初始化方法和销毁方法。
@Service("userService")
public class UserServiceImpl implements UserService {@PostConstructpublic void init(){System.out.println("对象初始化了");}@PreDestroypublic void destroy(){System.out.println("对象销毁了");}
}
5.2、测试
@Test
public void testUserServiceImpl() throws Exception{// 1、读取主配置文件信息,获取核心容器对象ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");ac.close();
}// 对象初始化了
// 对象销毁了
5.3、总结
这个两个注解作用就和在bean标签中使用init-method和destroy-methode的作用是一样的。