一、在classpath中扫描
1.1 在xml中指定需要扫描的组件component scanning
,并添加过滤器
<context:include-filter> 和 <context:exclude-filter>
子节点支持多种类型的过滤表达式
<!-- 可以通过resource-pattern 来选择需要扫描的包和类 -->
<context:component-scan base-package="com.spring.learn.annotation" resource-pattern="user/*.class">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
此时只会加载user的类,下面示例添加过滤器
<!-- 可以通过resource-pattern 来选择需要扫描的包和类 -->
<context:component-scan base-package="com.spring.learn.annotation" resource-pattern="user/*.class">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
测试类如下
添加注解情况如下:
UserController注解为 @Controller("userController")
UserService @Service("userService")
UserRepositoryImpl @Repository("userRepository")
@Test
void annotation(){
applicationContext=new ClassPathXmlApplicationContext("annotationContext.xml");
//AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
UserController userController = applicationContext.getBean("userController", UserController.class);
System.out.println(userController);
UserRepository userRepository = applicationContext.getBean("userRepository", UserRepository.class);
System.out.println(userRepository);
UserService userService = applicationContext.getBean("userService", UserService.class);
System.out.println(userService);
}
1.2 组件装配
Bean的后置处理器会自动注册AutoWiredAnnotationPost自动装配具有 @Autowired @Resource @InjectProcessor
即Bean的后置处理器,也可以使用set方法,注意:必须IoC容器有该类,即所有AutoWired都需要IoC容器需要有该实例,如果不需要可以把AutoWired注解值设为false。有多个实例时,使Bean的名字和属性名一致即可,若未配置名称,则使用@Qualifier("需要的属性名"),注解加到set方法参数、属性均可实现自动装配,@Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性
建议使用 @Autowired 注解
。
AutoWired属性详解
构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
@Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
@Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
@Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值。
1.3泛型注入
自动注入泛型对应的子类
1.4 使用完全注解,去掉xml文件
使用@Configuration来指定配置类,@ComponentScan来指定扫描的类路径,对加载的其他类,直接实现方法即可,方法的返回值会加载到容器中,需要使用@Bean,示例程序如下:
package com.spring.learn.annotation.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* Created with IntelliJ IDEA.
*
* @Author : gxm
* @Date : 2020/4/13
* @Time : 17:06
* @projectName : spring框架学习
* @Description :
* To change this template use File | Settings | File Templates.
* Description:
* 细节:使用注解配置方法时:Spring框架会去容器中查找是否有可用的Bean对象
**/
@Configuration
@ComponentScan(value = "com.spring.learn.annotation")
public class SpringConfiguration{
/**
* create by: ${USER}
* description: TODO
* create time: 2020/4/13 17:20
*
* @param source
* @return org.apache.commons.dbutils.QueryRunner
* @Description :
* Bean 将当前方法的返回值作为Bean对象存入Spring的IoC容器中
* name:用于指定Bean的id,默认值为当前方法的名称
*/
@Bean(name = "queryRunner")
@DependsOn(value = "javax.sql.DataSource")
public QueryRunner createQueryRunner( DataSource source){
return new QueryRunner(source);
}
/**
* create by: ${USER}
* description: TODO
* create time: 2020/4/13 17:23
*
* @param
* @return javax.sql.DataSource
* @Description : 创建数据源对象
*/
@Bean(name = "source")
public DataSource createDataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass("com.jdbc.mysql.Driver");
dataSource.setJdbcUrl("jdbc:mysql://*.*.*.*:3306/MeasureAgent");
dataSource.setUser("root");
dataSource.setPassword("123456789");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
}
- JUint测试,对configuration注解和传入配置类二选一即可,对于需要分离的配置时,可以使用Import将其他的类的字节码引入。
@Test
public void annotationTest(){
annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
UserController userController = annotationConfigApplicationContext.getBean("userController", UserController.class);
userController.execute();
System.out.println(userController);
UserRepository userRepository = annotationConfigApplicationContext.getBean("userRepository", UserRepository.class);
System.out.println(userRepository);
UserService userService = annotationConfigApplicationContext.getBean("userService", UserService.class);
System.out.println(userService);
}
1.5 加载外部属性文件
使用注解@PropertySource("classpath:db.properties")
加载外部属性文件,需要添加一个Bean PropertySourcesPlaceholderConfigurer
来表明属性文件的位置配置,同xml,然后在对应的属性上直接使用SpEL语言来对其进行赋值,示例如下:
package com.spring.learn.annotation.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* Created with IntelliJ IDEA.
*
* @Author : gxm
* @Date : 2020/4/13
* @Time : 19:49
* @projectName : spring框架学习
* @Description :
* To change this template use File | Settings | File Templates.
* Description:
**/
public class JdbcConfig {
@Value("${driverClass}")
private String driverClass;
@Value("${user}")
private String user;
@Value("${password}")
private String password;
@Value("${jdbcUrl}")
private String jdbcUrl;
/**
* create by: gxm
* create time: 2020/4/13 18:07
*
* @param source
* @return org.apache.commons.dbutils.QueryRunner
* @Description :
* Bean 将当前方法的返回值作为Bean对象存入Spring的IoC容器中
* name:用于指定Bean的id,默认值为当前方法的名称
*/
@Bean(name = "queryRunner")
@DependsOn(value = "source")
public QueryRunner createQueryRunner(DataSource source) {
return new QueryRunner(source);
}
/**
* create by: gxm
* create time: 2020/4/13 22:46
* @param
* @return org.springframework.context.support.PropertySourcesPlaceholderConfigurer
* @Description : 需要添加 PropertySourcesPlaceholderConfigurer 来加载属性文件
*/
@Bean(name = "propertySourcesPlaceholderConfigurer")
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
/**
* create by: ${USER}
* create time: 2020/4/13 17:23
*
* @return javax.sql.DataSource
* @Description : 创建数据源对象
*/
@Bean(name = "source")
@DependsOn("propertySourcesPlaceholderConfigurer")
public DataSource createDataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl(jdbcUrl);
dataSource.setUser(user);
dataSource.setPassword(password);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
}
1.6 整合Juint测试
- 首先配置注解
@RunWith(SpringJUnit4ClassRunner.class)
表示该测试类有Spring框架调用 - 指定配置的位置,如果是xml文件则指定location(示例:classpath:db.xml或者文件路径)如果是xml文件则指定classes 传入配置文件的字节码,配置示例如下:
@ContextConfiguration(classes = SpringConfiguration.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest {
@Autowired
QueryRunner queryRunner;
@Autowired
private UserController userController;
@Autowired
private UserRepository userRepository;
@Autowired
private UserService userService;
@Test
public void junitTest() {
System.out.println(queryRunner);
}
@Test
public void annotation() {
userController.execute();
System.out.println(userController);
System.out.println(userRepository);
System.out.println(userService);
}
@Test
public void annotationTest() {
userController.execute();
System.out.println(userController);
System.out.println(userRepository);
System.out.println(userService);
ArrayListHandler arrayListHandler = new ArrayListHandler();
try {
queryRunner.query("select * from icmp_data where id <5", arrayListHandler);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}