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