Spring17_注解开发7
一、Spring原始注解
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文 件可以简化配置,提高开发效率。
Spring原始注解主要是替代<Bean>的配置
注入的3个注解用来替代property注入的。
注意:使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。
<!--注解的组件扫描-->
<context:component-scan base-package="com.itheima"></context:component-scan>
1. 完善测试环境
执行main,可以看到控制台输出:save running ...,表明环境OK
2. 注解开发实现
执行UserController,输出成功
3. 实例化Bean的注解
上面使用的是Component注解,虽然能用但是不能确定是在哪层,所以建议使用Controller、Service、Repository注解去分清web层、service层、dao层
@Service("userService") public class UserServiceImpl implements UserService { ... ... }
@Repository("userDao") public class UserDaoImpl implements UserDao { ... ... }
4. 注入对象的注解
使用@Autowired或者@Autowired+@Qulifier或者@Resource进行userDao的注入
//<property name="userDao" ref="userDao"></property> @Autowired //按照数据类型从Spring容器中进行匹配的,可单独使用 private UserDao userDao; // public void setUserDao(UserDao userDao) { // this.userDao = userDao; // }
//<property name="userDao" ref="userDao"></property> @Autowired //按照数据类型从Spring容器中进行匹配的,可单独使用 @Qualifier("userDao") //ref值,按照id值从容器中进行匹配的,但是注意:@Qualifier需要结合@Autowired一起使用 private UserDao userDao; // public void setUserDao(UserDao userDao) { // this.userDao = userDao; // }
//<property name="userDao" ref="userDao"></property> @Resource(name="userDao") //name=id值,相当于@Autowired+@Qualifier private UserDao userDao; // public void setUserDao(UserDao userDao) { // this.userDao = userDao; // }
5. 注入普通属性的注解
package com.itheima.service.impl; import com.itheima.dao.UserDao; import com.itheima.service.UserService; 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.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; //<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> @Service("userService") public class UserServiceImpl implements UserService { @Value("itcast") private String name; @Value("${jdbc.driver}") private String driver; //<property name="userDao" ref="userDao"></property> @Resource(name="userDao") //name=id值,相当于@Autowired+@Qualifier private UserDao userDao; public void save() { System.out.println(name); System.out.println(driver); userDao.save(); } }
执行UserController,检查控制台输出
6. Scope注解
相当于bean标签里的scope,表示对象是单例,还是多例
//<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> @Service("userService") //@Scope("prototype") @Scope("singleton") public class UserServiceImpl implements UserService { ... ... }
7. 初始化方法、销毁方法的注解
相当于bean标签中的init-method、destroy-method
package com.itheima.service.impl; import com.itheima.dao.UserDao; import com.itheima.service.UserService; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; 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.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; //<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"> @Service("userService") @Scope("singleton") public class UserServiceImpl implements UserService { @Value("itcast") private String name; @Value("${jdbc.driver}") private String driver; //<property name="userDao" ref="userDao"></property> @Resource(name="userDao") //name=id值,相当于@Autowired+@Qualifier private UserDao userDao; public void save() { System.out.println(name); System.out.println(driver); userDao.save(); } @PostConstruct public void init(){ System.out.println("init..."); } @PreDestroy public void destroy(){ System.out.println("destroy..."); } }
package com.itheima.web; import com.itheima.service.UserService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserController { public static void main(String[] args) { ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = app.getBean(UserService.class); userService.save(); app.close(); } }
执行UserController,检查控制台输出
二、Spring新注解
使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:
- 非自定义的Bean的配置:<Bean>,例如上面的<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">,ComboPooledDataSource这个不是自定义的
- 加载properties文件的配置:<context:property-placeholder>
- 组件扫描的配置:<context:component-scan>
- 引入其他文件:<import>
新注解:
1. Configuration注解
不要xml配置文件并不意味着没有配置,Configuration注解是用类的方式去代替xml配置文件,用注解的方式去代替标签。
2. ComponentScan注解
见上图,代替指定Spring在初始化容器时要扫描的包
3. PropertySource注解、Bean注解
DataSourceConfiguration.java类-数据源配置:
package com.itheima.config; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import javax.sql.DataSource; //<context:property-placeholder location="jdbc.properties"/> @PropertySource("classpath:jdbc.properties") public class DataSourceConfiguration { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /* <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> */ @Bean("dataSource") //Spring会将当前方法的返回值以指定名称存储到Spring容器中 public DataSource getDataSource() throws Exception { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } }
4. Import注解
加载配置时只会加载核心配置类即SpringConfiguration,不会加载DataSourceConfiguration,所以需要在核心配置类时引入加载DataSourceConfiguration
核心配置类中可以引入多个非核心配置类,如:@Import({DataSourceConfiguration.class, Test.class})
5. 测试加载核心配置类创建Spring容器
至此,applicationContext.xml里的标签全都用注解实现,这时可以把配置文件删掉了。
加载核心配置文件的代码就需要改成加载核心配置类代码
package com.itheima.web; import com.itheima.config.SpringConfiguration; import com.itheima.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; public class UserController { public static void main(String[] args) throws SQLException { // ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class); UserService userService = app.getBean(UserService.class); userService.save(); DataSource dataSource = (DataSource) app.getBean("dataSource"); Connection connection = dataSource.getConnection(); System.out.println(connection); } }