Spring注解开发
1、Spring原始注解
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml文件以后可以简化配置,提高我们的开发效率
- Spring原始注解主要是替代标签的配置
- 主要的原始注解有
2、完善我们的开发环境
2.1、先创建xml然后开始对比注解的方式
-
创建dao层和Service还有web层的准备工作
-
package com.waves.dao; // dao层 public interface UserDao { // 写了一个底层的save方法 public void save(); } // UserDao的实现类 package com.waves.dao.impl; import com.waves.dao.UserDao; public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("save running....."); } } // Service层 package com.waves.service; public interface UserService { // 调用底层的save方法 public void save(); } // 业务层的实现类 public class UserServiceImpl implements UserService { // 将UserDao对象注入到UserService对象中--采用set的方法 private UserDao userdao; // 初始化 public void setUserdao(UserDao userdao) { this.userdao = userdao; } @Override public void save() { System.out.println("底层的save方法被调用......"); userdao.save(); } } // web层 public class UserController { // 调用底层的save方法 public static void main(String[] args) { // 加载配置文件 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取UserService对象 UserService service = app.getBean(UserService.class); service.save(); } }
-
运行结果
2.2、注解开发代替xml配置文件
2.2.1、将需要注入到容器的组件进行注入
@Componet(id)–一定要写id,spring识别不出来
@Qualifier(“userDao”),你想要将哪个组件注入进来,就在里面写那个组件的id
@Autowried–自动注入
// 注解的方式帮我注入到容器中
@Component("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save running.....");
}
}
@Component("userService")
public class UserServiceImpl implements UserService {
// 将UserDao对象注入到UserService对象中--采用set的方法
@Autowired //自动注入
@Qualifier("userDao") // 没懂
private UserDao userdao;
// 初始化
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
@Override
public void save() {
System.out.println("底层的save方法被调用......");
userdao.save();
}
}
2.2.2、将UserDao对象注入到Service中
@Autowired //自动注入
@Qualifier("userDao") // 没懂
private UserDao userdao;
2.2.3、配置扫描组件–xml中配置
<!-- 配置组件扫描,告诉Spring我那些包下的组件需要被扫描和注入 -->
<context:component-scan base-package="com.waves"></context:component-scan>
2.2.4、测试
3、原始注解详解
原先注解的弊端,Componet注解无法明了,创建的组件,是哪个层的,语义不明确
3.1、@Repositpry,@Service,@Controller(现在用不上)
将原先dao层和service层的注解修改一下,明确语义
@Repository("userDao")
@Service("userService")
3.2、关于@Qualifier(名称注入)和@Autowired注解(类型注入)
-
@Qualifier会和Autowired相互配合,但是
-
如果没有@Qualifier注解,@Autowired注解会从Spring的容器中进行匹配
-
例如这个例子
-
@Autowired //自动注入 // @Qualifier("userDao") // 没懂 private UserDao userdao;
-
我取消了@Qualifier这个注解,那么@Autowired能不能给我注入呢?当然是可以的
-
因为我为UserDao对象注入到了容器当中
-
问题,如果容器当中存在多个UserDao的对象,那么这个时候@Autowired就不可以了,因为他不知道你到底需要将哪个UserDao对象依赖注入进来,所以需要@Qualifier来指定对象的的id,他会根据id从容器中进行匹配,并且必须依赖于@Autowired注解
3.3、@Resource注解(= @Qualifier + @Autowired)
@Resource的name值就是组件的id值
@Resource(name="userDao")
private UserDao userdao;
3.4、value注解
3.4.1、可以注入普通值–鸡肋
-
我在这里设置一个变量名,然后通过value注入一个很普通的值
-
直接赋值就是普通的注入
// Value注入普通的值
@Value("instruct")
private String driver;
@Override
public void save() {
System.out.println("我的driver值是:"+driver);
System.out.println("底层的save方法被调用......");
userdao.save();
}
- 运行结果
3.4.2、复杂类型的注入,properties–@Value(${})
-
先把properties注入到xml配置文件中
-
<!-- 属性加载器 --> <context:property-placeholder location="classpath:jdbc.properties"/>
-
//@Value("instruct") // 复杂类型的注入 @Value("${jdbc.driver}") private String driver; @Override public void save() { System.out.println("我的driver值是:"+driver); System.out.println("底层的save方法被调用......"); userdao.save(); }
-
测试
-
注入成功!
4、Spring新注解
使用新注解的原因,因为原始注解无法替代,第三方的bean,加载properties的配置文件context:property-placeholder,组件扫描context:componet-scan,引入其他配置文件import,这些都是我们原始注解无法进行替换的
4.1、新注解学习流程
4.2、@Configuration–配置类
该类是Spring的一个核心配置类–用一个类的方式代替文件,注解的方式代替标签,他的目的就是为了替代xml配置文件
-
创建我们的配置类
-
package com.waves.conifg; import org.springframework.context.annotation.Configuration; // 这个是我们的核心配置类--目的是为了替代核心配置文件application.xml @Configuration public class SpringDatasourceConfig { }
4.3、@ComponentScan–包扫描,容器对象创建需要扫描的包是谁?
-
在配置类的基础上加上@ComponentScan
-
// 这个是我们的核心配置类--目的是为了替代核心配置文件application.xml @Configuration // <context:component-scan base-package="com.waves"></context:component-scan> @ComponentScan("com.waves") public class SpringDatasourceConfig { }
4.4、@Bean注解,解决第三方给我们创建的接口的调用–创建在方法上,方法的返回值对象会注入到容器当中
-
在原有基础上加上@Bean注解
-
import javax.activation.DataSource; // 这个是我们的核心配置类--目的是为了替代核心配置文件application.xml @Configuration // <context:component-scan base-package="com.waves"></context:component-scan> @ComponentScan("com.waves") public class SpringDatasourceConfig { // 创建我们的第三方返回值对象 @Bean("dataSource") public DataSource getDataSource() { return new DataSource(); } }
4.5、@PropertySource注解,替换xml中导入properties的方法
导入值还是要从外面导入的,不能再方法内部导入,因为他会把SPL表达式当成字符串
-
导入效果
-
// 这个是我们的核心配置类--目的是为了替代核心配置文件application.xml @Configuration // <context:component-scan base-package="com.waves"></context:component-scan> @ComponentScan("com.waves") @PropertySource("classpath:jdbc.properties") public class SpringDatasourceConfig { // 需要注入值的对象 @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.user}") private String user; @Value("${jdbc.password}") private String password; // 创建我们的第三方返回值对象 @Bean("dataSource") public ComboPooledDataSource getDataSource() throws PropertyVetoException { // 对数据源数据进行注入 ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(user); dataSource.setPassword(password); return dataSource; } }
4.6、@Import注解,该注解用于主配置文件导入副配置文件的作用
-
我创建第二个配置类,这个类作为我们的主配置类
-
导入Import,数据库配置类的注解
-
@PropertySource,这个注解谁需要谁才加入–建议
-
// 这个类是我们的主配置类 @Configuration // 配置包扫描 @ComponentScan("com.waves") // 导入我们的数据库配置类 @Import(SpringDatasourceConfig.class) public class SpringConfigurataion { }
4.7、引入配置类–AnnotationConfigApplicationContext–舍弃了xml配置文件
-
实战效果
-
顺便查看我们的那个数据库对象是否成功引用到了
-
public class UserController { // 调用底层的save方法 public static void main(String[] args) throws SQLException { // 加载配置文件 //ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfigurataion.class); // 获取UserService对象 UserService service = app.getBean(UserService.class); service.save(); // 获取数据库的对象 ComboPooledDataSource dataSource = (ComboPooledDataSource) app.getBean("dataSource"); Connection connection = dataSource.getConnection(); System.out.println(connection); } }
-
实战效果
-
very deep!