- 注:这是学习过程的一些个人笔记,可能理解不够,会有错误的地方。
#Spring的注解使用
在Spring中有全XML方式,还有半注解方式,还有全注解方式,半注解方式是因为我们在使用Spring时可能需要第三方的Jar包,对于第三方的包我们是无法在其源代码上加入注解的,我们只能在我们自己的类中加入注解,因此是半注解方式,而全注解方式,我们其实也是无法在第三方的类中加代码,但是我们可以创建一个注解类,然后我们自己在注解类中实例化对象,将对象交于IOC容器管理,这样来实现全注解的方式。
半注解代码示例
在使用注解之前,这里先用一个示例来演示Spring如何管理第三方的对象。这里我用Spring整合c3p0来当做例子,要使用c3p0除了Spring基本包还需要导入两个包。
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar–c3p0的包
mysql-connector-java-5.0.4-bin.jar–MySQL驱动包
- 配置文件示例
<?xml version="1.0" encoding="UTF-8"?>
<!-- beans的约束文件 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 如果要整合连接池就需要用到context,要使用context需要在beans中写入context的名称空间以及约束文件
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
-->
<!-- 因为Spring可以管理别人提供的类,因此这里整合c3p0连接池可以直接使用普通的属性注入方式
例如:<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
这里用另一种方式,使用配置文件方式,首先需要创建一个jdbc.properties文件放在src下,
文件中是数据库参数的键值对,如:driverClass=com.mysql.jdbc.Driver
然后在spring的配置文件中使用数据库的配置文件
context:property-placeholder表明要使用哪个地方的数据库配置文件
location="classpath:jdbc.properties"表明加载类路径下的配置文件
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 这里就和创建普通的bean一样,class为c3p0的全类名
property为属性的依赖注入,name为要注入的属性名,属性在c3p0中
value这里使用的表达式为${数据库配置文件中的键},这是spring的表达式
-->
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
</bean>
</beans>
- 测试类示例
@Test
public void test2() throws Exception{
//加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取c3p0连接池对象
ComboPooledDataSource dataSource = (ComboPooledDataSource)context.getBean("c3p0");
//获取连接
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
这里开始演示半注解的方式,如果要使用注解除了Spring基本包还需要导入aopJar包—spring-aop-4.2.4.RELEASE.jar
- 半注解的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- beans的约束文件 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 在半注解中,别人的类还是使用xml配置方式 -->
<!-- 加载数据库连接池的参数配置 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- c3p0的配置 -->
<bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 自己的类使用注解代替 -->
<!-- 如果要使用注解,需要导入aop的jar包
需要在配置文件中配置context:component-scan
表明需要扫描哪个包下的注解,只有该包和子包下的注解才会被承认
这是属于半注解的方式,全注解就是连配置文件都不需要了
-->
<context:component-scan base-package="com.wzm"></context:component-scan>
</beans>
- 半注解的JavaBean类
package com.wzm.entity;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
/*
* 老师类
*/
/*
* @Component("tea")+@Scope("singleton")相当于
* <bean id="tea" class="com.wzm.entity.Teacher" scope="singleton"></bean>
* @Component("tea")表名需要将该类的实例化交予spring管理,参数即为bean的di值
* 注意:该注解spring已经不再维护,spring推出三个与该注解功能一样的注解,这是为了体现出分层的效果
* @Controller用在表现层servlet或者action
@Service用在业务层service
@Repository用在持久层也就是Dao层
*
*/
@Component("tea")
@Scope("singleton")
public class Teacher {
/*
* 这是使用注解的属性依赖注入方式
* @Value("老师")相当于<property name="name" value="老师"></property>
* 注意同样针对基本类型和String,使用注解就不需要setter方法
*/
@Value("老师")
private String name;
/*
* 这是使用注解的属性依赖注入方式
* @Autowired是针对对象类型的注入,默认spring对自己去找有没有与属性相同类型的bean来注入
* @Qualifier("stu")如果使用了就会找bean的id值为该注解内参数相同的bean来注入
* 相当于<property name="name" ref="stu"></property>
* 注意当@Qualifier使用在属性上时,只能与Autowired配合出现,不能单独出现
*
* 还有几个属于apache的注解
* @Resource相当于@Autowired+@Qualifier
@PostConstruct用在方法上,表明该方法为初始化方法
@PreDestroy用在方法上,表明该方法为对象销毁前执行的方法
*/
@Autowired
@Qualifier("stu")
private Student student;
@Override
public String toString() {
return "Teacher [name=" + name + ", student=" + student + "]";
}
}
- 测试类
@Test
public void test1() {
//半注解方式还是需要加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象
Teacher teacher = (Teacher) context.getBean("tea");
System.out.println(teacher);
}
全注解代码示例
在半注解中,c3p0的使用还是得在配置文件中配置相关参数,在全注解的方式中就不需要了,不再有配置文件,全注解除了自己类还是同样的注解方式,使用一个注解类来代替配置文件。
- 注解类示例
package com.wzm.entity;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/*
* 当想要完全抛弃配置文件使用全注解时,我们就需要创建一个配置类
* @Configuration表明该类是一个配置类
* @ComponentScan表明扫描使用注解的包,相当于
* <context:component-scan base-package="com.wzm"></context:component-scan>
* 因为当我们使用全注解的方式时,我们就可以通过注解方式来获得别人提供的类,例如c3p0
* 这是如果我们需要c3p0的数据库连接配置文件,就需要使用注解
* @PropertySource(value="classpath:jdbc.properties"),classpath表明加载类路径下的文件
*/
@Configuration
@ComponentScan(basePackages="com.wzm")
@PropertySource(value="classpath:jdbc.properties")
public class AnnotationConfig {
/*
* 这里是使用依赖注入的方式注入属性值,
* ${driverClass}表明注入值为数据库配置文件中的值
* 注意如果spring版本是4.3以下的,需要配置一个占位器,注解才能使用这种表达式
* PropertySourcesPlaceholderConfigurer
*/
@Value("${driverClass}")
private String driver;
@Value("${jdbcUrl}")
private String jdbcUrl;
@Value("${user}")
private String user;
@Value("${password}")
private String password;
/*
* 因为c3p0是别人的东西,我们不能在他们的源码使用注解,这时我们只能自己创建对象,然后把对象交给IOC容器,
* 当我们要使用这个对象时,就从IOC容器拿,归根来说,这个对象还是我们自己创建的,不是spring帮我们实例化的
* @Bean(name="c3p0")表明要将我们创建的对象交给spring,name为我们要取对象时用的id值
*/
@Bean(name="c3p0")
public DataSource createDateSource() throws Exception {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(jdbcUrl);
ds.setUser(user);
ds.setPassword(password);
return ds;
}
/*
* 低版本需要的占位器
*/
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
- 测试类
@Test
public void test3() throws SQLException{
//因为使用全注解方式没有了配置文件,因此也就无法加载配置文件了
//这里就需要加载配置类,AnnotationConfigApplicationContext就是用来加载配置类的,参数为配置类的class对象
ApplicationContext config = new AnnotationConfigApplicationContext(AnnotationConfig.class);
//获取c3p0连接池对象
ComboPooledDataSource dataSource = (ComboPooledDataSource)config.getBean("c3p0");
//获取连接
Connection conn = dataSource.getConnection();
System.out.println(conn);
}
整合Junit
因为在做测试时,每一个测试都需要加载一遍配置文件,为了避免这种情况,Spring整合了Junit,由Spring来加载配置文件,Junit只做原本的测试功能。要整合Junit使用半注解方式,因此配置文件与之前同样配置,同时需要的Jar包除了注解需要的aop包,还要有Junit的包和一个test包。
junit.jar和spring-test-4.2.4.RELEASE.jar
- 整合Junit后的测试类示例
package com.wzm.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.wzm.entity.Teacher;
/*
* spring整合Junit的方式
* 因为在使用Junit时每一个测试都需要加载一遍配置文件,但是配置文件只需要加载一次就够了
* 因此spring整合了junit,让spring来加载配置文件
* 而junit还是一样负责原来的测试功能就好了
*/
/*
* @RunWith表明要将配置文件交于谁来加载
* SpringJUnit4ClassRunner.class就是spring用来加载配置文件的类
*/
@RunWith(SpringJUnit4ClassRunner.class)
/*
* 因为不需要再在junit测试中加载配置文件,因此这里需要指明配置文件的位置
* @ContextConfiguration表明配置文件的位置
*/
@ContextConfiguration(value="classpath:applicationContext.xml")
public class JunitTest {
/*
* 因为没有获取配置文件对象来获取bean对象,因此需要用到注解的属性注入
*/
@Autowired
private Teacher teacher;
/*
* 这里是普通的test测试,只是不需要再加载配置文件了
*/
@Test
public void Test() {
System.out.println(teacher);
}
}