使用@Component注解的问题
@Component的缺点:该注解只能作用于类上,对于自定的类操作很方便,但是对于引入的第三方包来说很麻烦,而且往往没有这些包的源码,这样就无法在类上添加@Component注解。
问题的解决方案:
(1)定义新的类继承jar包中的类,然后在新类上添加@Component注解。
(2)使用Spring提供的注解@Bean
下面介绍注解@Bean的使用:
@Bean的使用也很简单,@Bean可以注解在方法上,并将方法返回的对象作为Spring的bean存放到Ioc容器中。@Bean不能使用在类上
@Bean注解有四个配置项:
(1)name:字符串数组
(2)autowire:标志是否是一个引用的Bean对象,默认值为Autowire.NO
(3)initMethod:自定义初始化方法
(4)destroyMethod:自定义销毁方法
下面实现一个案例,该案例囊括@Component、@ComponentScan、@Bean等注解
在实现案例前回答一个问题,何时使用注解形式,何时使用XML配置?
杨开振那本书中推荐将自己写的类使用注解形式、将第三方包或者服务类使用xml方式
(1)我使用maven构建项目,首先配置依赖,我们所用的包共三个,分别是spring-context、junit、mysql-connector-java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>(2)创建t_role数据库
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_name` varchar(32) NOT NULL,
`note` varchar(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `role_name` (`role_name`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8(3)创建properties文件,文件内容为数据库相关的键值对
jdbc.database.driver = com.mysql.jdbc.Driver
jdbc.database.url = jdbc:mysql://localhost:3306/ssm
jdbc.database.username = root
jdbc.database.password = 123456(4)使用@PropertySource将properties文件导入Spring的environment中,并且使用@ComponentScan告诉Spring扫描加入Ioc容器中的bean
在ApplicationConfig2中的逻辑的作用:让Spring解析属性文件并通过占位符引用对应的配置,即properties中的属性可以使用占位符进行引用。
package com.ssm.spring.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.stereotype.Component;
@ComponentScan(basePackages = {"com.ssm.spring.annotation"})
@PropertySource(value={"classpath:database-config.properties"},ignoreResourceNotFound = true)
public class ApplicationConfig2 {
//Spring解析属性文件并通过占位符引用对应的配置
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
}(5)创建DataSource数据源,并使用@Bean注解将方法中返回的对象加入Spring的Ioc容器中。
其中@Component注解作用:将DataSourceBean加入Ioc容器中;
@Value注解作用:使用Spring表达式将properties中的值引入给成员变量赋值。
@Bean注解作用:将返回的数据源datasource加入Ioc容器中;
package com.ssm.spring.annotation.config;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.Properties;
@Component
public class DataSourceBean {
@Value("${jdbc.database.driver}")
private String driver = null;
@Value("${jdbc.database.url}")
private String url = null;
@Value("${jdbc.database.username}")
private String username = null;
@Value("${jdbc.database.password}")
private String password = null;
@Bean
public DataSource getDataSource()
{
Properties props = new Properties();
props.setProperty("driver",driver);
props.setProperty("url",url);
props.setProperty("username",username);
props.setProperty("password",password);
DataSource dataSource = null;
try {
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
return dataSource;
}
}
(6)创建与数据库表对应的类,用于接收查询结果
package com.ssm.spring.annotation.pojo;
public class Role {
private Long id;
private String roleName;
private String note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", note='" + note + '\'' +
'}';
}
}
(7)建立数据库连接,并根据id查询角色并输出
创建接口,该接口有getRole方法,该方法需要根据id查询角色信息
package com.ssm.spring.annotation.service;
import com.ssm.spring.annotation.pojo.Role;
public interface RoleDataSourceService {
public Role getRole(Long id);
}
创建RoleDataSourceServiceImpl实现上述接口,该实现类连接数据库获取数据库的角色信息。
@Component注解表明该类是需要装入Ioc容器中的bean
@Autowired注解表明需要将Ioc容器中的数据池自动装配
之后该段代码重写getRole方法,进行数据库的连接,查找,最后返回Role对象实例
package com.ssm.spring.annotation.service.Impl;
import com.ssm.spring.annotation.pojo.Role;
import com.ssm.spring.annotation.service.RoleDataSourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@Component
public class RoleDataSourceServiceImpl implements RoleDataSourceService {
@Autowired
DataSource dataSource = null;
@Override
public Role getRole(Long id) {
Connection conn = null;
ResultSet rs = null;
PreparedStatement ps = null;
Role role = null;
try{
conn = dataSource.getConnection();
String sql = "select id,role_name,note from t_role where id = ?";
ps = conn.prepareStatement(sql);
ps.setLong(1,id);
rs = ps.executeQuery();
while(rs.next())
{
role = new Role();
role.setId(rs.getLong("id"));
role.setRoleName(rs.getString("role_name"));
role.setNote(rs.getString("note"));
}
}catch(SQLException e)
{
e.printStackTrace();
}finally {
if(rs!=null)
{
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null)
{
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null)
{
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return role;
}
}
(8)编写测试代码进行测试
public void test1()
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig2.class);
RoleDataSourceService service = context.getBean(RoleDataSourceService.class);
Role role = service.getRole(1L);
System.out.println(role);
}
查询到数据库中id为1的信息