JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)
JavaEE学习日志(八十九)
Spring注解开发
注解开发入门
1、引入依赖
2、配置文件
- 头文件增加命名空间和约束
- 开启注解
<context:component-scan base-package="包名"></context:component-scan>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
">
<!--
开启注解,指定扫描的包:context:component-scan
引入context名称空间,引入约束
base-package:指定要扫描的包,扫描的是包和其子包
-->
<context:component-scan base-package="com.itheima"></context:component-scan>
</beans>
3、在需要创建的类上添加注解@Component
package com.itheima.dao.impl;
import com.itheima.dao.UserDao;
import org.springframework.stereotype.Component;
@Component
public class UserDaoImpl implements UserDao {
}
4、测试
@Test
public void test(){
//创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象
UserDao userDao = ac.getBean(UserDao.class);
System.out.println(userDao);
}
Component注解
@Component
标志在类上,不能用在方法上
作用:只要扫描了包,就会创建对象
1、衍生了三个子注解
@Controller
一般用于web层@Service
一般用于业务层@Repository
一般用于持久层
作用:三个的作用和@Component
都是一样的,但最好别混用。
2、@Component
中有个属性value=""
可以用于指定名字,默认的名称是简单类名首字母小写
(UserServiceImpl->userServiceImpl)
@Component("userService")
相当于xml中
<bean id="userService" class="全限类名"></bean>
自动注入@Autowired
如果想在UserService中调用UserDao,则只需要加上@Autowired
注解即可。
可以标记在属性或set方法上,如果标记在属性上,可以没有set方法
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
public void print(){
userDao.print();
}
}
特点:自动按照类型注入
流程:当属性或方法(set方法)标记了@Autowired
,那么会自动在容器中查找该属性类型的对象,如果有且只有一个,则注入。
注意:如果有两个userDao的实现类,则会报错。
解决方法:
一、在@Autowired
下配置上需要注入的名称,使用注解@Qualifier
@Qualifier("userDaoImpl2")
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDaoImpl2")
UserDao userDao;
public void print(){
userDao.print();
}
}
二、根据属性名注入
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDaoImpl2;
public void print(){
userDaoImpl2.print();
}
}
自动注入@Resource
如果没有@Resource
注解,则写入依赖
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
流程:当属性或方法(set方法)标记了@Resource
- 按照名称查找:会自动按照名称注入,如果指定了名称,则按照名称注入;如果没有指定名字,则按照属性名注入。
- 按照类型查找:如果名称没有找到,则按照类型注入;类型有多个则抛出异常
按照指定的名称注入
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name="userDaoImpl2")
UserDao userDao;
public void print(){
userDao.print();
}
}
按照属性名注入
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
UserDao userDaoImpl2;
public void print(){
userDaoImpl2.print();
}
}
按照类型注入(属性名找不到对应的类时):如果有多个则报异常
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
UserDao userDao;
public void print(){
userDao.print();
}
}
@Autowired
和@Resource
区别
@Autowired
:
- 默认按照类型注入,如果类型有多个,则按照名称注入
- spring提供
@Resource
:
- 默认按照名称注入,如果名称没有找到,则按照类型注入
- jdk提供
使用半注解半xml改造账户CRUD
开启注解中有两个属性
1、context:include-filter
:指定包含过滤
type="annotation"
按照类型过滤expression=""
过滤的表达式
在下边代码中的含义:只扫描标记了Controller注解的类
2、context:exclude-filter
:指定排除过滤
type="annotation"
按照类型过滤expression=""
过滤的表达式
在下边代码中的含义:除了Controller注解都会扫描
<!--开启注解,扫描包-->
<context:component-scan base-package="com.itheima">
<!--
context:include-filter:指定包含过滤
type="annotation"按照类型过滤
expression=""过滤的表达式
只扫描标记了Controller注解的类
-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--
context:exclude-filter:指定排除过滤
type="annotation"按照类型过滤
expression=""过滤的表达式
除了Controller注解都会扫描
-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!--开启注解,扫描包-->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!--创建qr对象,需要数据源对象,通过构造方法的参数类型注入-->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
</bean>
<!--创建数据源对象:需要注入四个参数,通过set方法注入-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
AccountDaoImpl
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
@Autowired
QueryRunner qr;
//...省略
}
AccountServiceImpl
import com.itheima.dao.AccountDao;
import com.itheima.dao.impl.AccountDaoImpl;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("accountService")
public class AccountServiceImpl implements AccountService {
//创建容器,使用依赖注入
@Autowired
private AccountDao accountDao;
//...省略
}
测试类
@Test
public void test(){
//创建容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//创建service对象
AccountService accountService = ac.getBean("accountService",AccountService.class);
List<Account> accountList = accountService.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
纯注解开发案例
使用纯注解改造账户CRUD
一、创建SpringConfiguration.java
- 标记该类为配置文件类
@Configuration
- 指定注解扫描的包路径
@ComponentScan({"com.itheima"})
- 引入其他配置文件类
@Import({JDBCConfiguration.class})
package com.itheima.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* 1、标记该类为配置文件类 @Configuration
* 2、指定注解扫描的包路径 @ComponentScan({"com.itheima"})
* 3、引入其他配置文件类 @Import({JDBCConfiguration.class})
*
*
*/
@Configuration
@ComponentScan({"com.itheima"})
@Import({JDBCConfiguration.class})
public class SpringConfiguration {
}
二、创建JDBCConfiguration.java
@Configuration
:可以省略@Bean("name")
:用在方法上,用来指定方法创建的对象存到容器中,一般用于别人的类,相当于<bean>
标签
"name"就是在容器中的名称
package com.itheima.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 配置持久层的对象
* @Configuration:可以省略
* @Bean("name"):用在方法上,用来指定方法创建的对象存到容器中
* "name"就是在容器中的名称
*
*/
@Configuration
public class JDBCConfiguration {
@Bean("queryRunner")
public QueryRunner createQueryRunner(DataSource dataSource){
//需要通过构造方法,注入dataSource
QueryRunner queryRunner = new QueryRunner(dataSource);
return queryRunner;
}
/**
* 创建数据源对象:dataSource
* @return
*/
@Bean("dataSource")
public DataSource createDataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUser("root");
dataSource.setPassword("root");
try {
dataSource.setDriverClass("com.mysql.jdbc.Driver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
}
三、测试
注意:使用ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
@Test
public void test(){
//创建容器
// ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//纯注解创建容器对象
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
//创建service对象
AccountService accountService = ac.getBean("accountService",AccountService.class);
List<Account> accountList = accountService.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
改造纯注解
改造一:数据库的一些属性写死了,把他们放到配置文件中
@PropertySource({"jdbc.properties"})
引入properties文件@Value
给属性赋值
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root
package com.itheima.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.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 配置持久层的对象
* @Configuration:可以省略
* @Bean("name"):用在方法上,用来指定方法创建的对象存到容器中
* "name"就是在容器中的名称
*
*/
@Configuration
@PropertySource({"jdbc.properties"})
public class JDBCConfiguration {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driverClass;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("queryRunner")
public QueryRunner createQueryRunner(DataSource dataSource){
//需要通过构造方法,注入dataSource
QueryRunner queryRunner = new QueryRunner(dataSource);
return queryRunner;
}
/**
* 创建数据源对象:dataSource
* @return
*/
@Bean("dataSource")
public DataSource createDataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
try {
dataSource.setDriverClass(driverClass);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
}
改造二:创建的对象默认是单例模式,将他改成多例模式
在类上添加注解@Scope("prototype")
@Repository("accountDao")
@Scope("prototype")
public class AccountDaoImpl implements AccountDao
改造三:可以添加对象的初始化和销毁方法(一般不用)
@PostConstruct
:相当于bean标签的属性init-method,指定初始化方法@PreDestroy
:相当于bean标签的属性:destroy-method,指定对象的销毁方法
xml引入外部文件
一、xml中引入xml
关键代码
<import resource="classpath:applicationContext-dao.xml"></import>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--引入外部属性文件-->
<import resource="classpath:applicationContext-dao.xml"></import>
<!--创建AccountService对象:需要AccountDao对象,依赖注入dao对象-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
</beans>
applicationContext-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--创建AccountDao对象,需要qr-->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<!--通过set方法注入qr-->
<property name="qr" ref="qr"></property>
</bean>
<!--创建qr对象,需要数据源对象,通过构造方法的参数类型注入-->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
</bean>
<!--创建数据源对象:需要注入四个参数,通过set方法注入-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
二、xml中引入properties文件
关键代码
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
applicationContext-dap.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!--创建AccountDao对象,需要qr-->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<!--通过set方法注入qr-->
<property name="qr" ref="qr"></property>
</bean>
<!--创建qr对象,需要数据源对象,通过构造方法的参数类型注入-->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
</bean>
<!--创建数据源对象:需要注入四个参数,通过set方法注入-->
<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>
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
</beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root