Spring是輕代碼而重配置的框架,配置比較繁重,影響開發效率,因此註解開發是一種趨勢,註解代替xml配置文件能夠簡化配置,提升開發效率
你原本要寫一段很長的代碼來構造一個Beam對象,可是若是使用註解的話只要使用一個註解符號便可
java
下面咱們來說講一些常常使用的註解符號
@Component 使用類上用於實例化Bean
@Controller 使用web層類上用於實例化Bean
@Service 使用在Service層類上用於實例化service
@Repository 使用在dao層類上用於實例化Bean
@Autorwired 使用在字段上用於根據類型依賴注入
@Qualifier 結合結合@Autowired一塊兒使用根據名稱進行依賴注入
@Resource 至關於@Autowired+@Qualifier一塊兒使用
@Scope 標註bean的範圍
@PostConstruct 使用該在方法上標註該方法是Bean的初始化方法
@PostDestory 使用在方法上標註該方法是Bean的銷燬方法web
這三個沒有什麼區別,不過是爲了在後期讀代碼的時候更加利於咱們區分,好比看到@Controller就知道這是web層,看到@Service就知道這是service層spring
@Component 使用類上用於實例化Bean @Controller 使用web層類上用於實例化Bean @Service 使用在Service層類上用於實例化service @Repository 使用在dao層類上用於實例化Bean
因此咱們只需講一個便可,其餘的使用方法均相同,這裏咱們使用@Component來說解
定義一個userDaolmp類sql
package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.stereotype.Component; @Component("userDaoImp") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } }
定義一個測試類測試apache
@Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); userdao userDaoImp =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); userDaoImp.save(); }
而後咱們就發現了以下報錯
由藍色的劃線部分咱們能夠看出問題是:沒有一個名叫userDaoImp的bean
這是爲什呢?由於咱們雖然寫了註解,可是咱們要讓applicationContext.xml知道咱們使用了註解,要告訴他哪裏有個bean。因此咱們在applicationContext中還須要加入如下配置api
命名空間:xmlns:context="http://www.springframework.org/schema/context
約束路徑:http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
註解的組件掃描:
<context:component-scan base-package="com.pjh"/>tomcat
成功運行
app
方式一:使用@Autowired+@Qualifier
目的:建立一個userdao類將其注入帶service類中框架
userdao類代碼maven
package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.stereotype.Component; @Component("userDaoImp") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } }
service類代碼
package com.pjh.service.Imp; import com.pjh.dao.Imp.userdao; import com.pjh.dao.userDaoImp; import com.pjh.service.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import javax.annotation.Resource; import javax.xml.bind.SchemaOutputResolver; @Repository("serviceImp") public class serviceImp implements service { @Autowired @Qualifier("userDaoImp") private userDaoImp userDaoImp; public void save() { System.out.println("sssssss"); userDaoImp.save(); } }
測試類
@Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); service service =(service) classPathXmlApplicationContext.getBean("serviceImp"); service.save(); }
結果
方式二:使用@Resource()
就是把 @Autowired + @Qualifier("userDaoImp")換成@Resource(name="userDaoImp"),其他代碼均與方式一相同
package com.pjh.service.Imp; import com.pjh.dao.Imp.userdao; import com.pjh.dao.userDaoImp; import com.pjh.service.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import javax.annotation.Resource; import javax.xml.bind.SchemaOutputResolver; @Repository("serviceImp") public class serviceImp implements service { /* @Autowired @Qualifier("userDaoImp")*/ @Resource(name="userDaoImp") private userDaoImp userDaoImp; public void save() { System.out.println("sssssss"); userDaoImp.save(); } }
結果
使人蛋碎的事情來了,報錯了,意思是不支持版本5
解決方案:
File->setting下設置項目的jdk版本
File->ProjectStruct下設置版本
結果
又報錯了,這。。。。。我tm心態崩了呀
根據報錯的內容是報了個空指針異常,這是爲何呢?爲何使用@Autowired + @Qualifier("userDaoImp")不報錯換成@Resource(name="userDaoImp")就報空指針呢
緣由:jdk版本不支持
解決方案:
1.更換本地的jdk版本,最好jdk1.8以上,jdk9不支持有bug
2.再maven.pom文件中引入以下依賴
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-annotations-api</artifactId> <version>7.0.47</version> </dependency>
結果
成功運行
終於解決完了
使用@Scope註解標註Bean的範圍
使用@Scope("prototype")
package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component("userDaoImp") @Scope("prototype") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } }
測試代碼
@Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); userdao userdao =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); userdao userdao1 =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); System.out.println(userdao); System.out.println(userdao1); }
結果
使用@Scope("singleton")
package com.pjh.dao; import com.pjh.dao.Imp.userdao; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component("userDaoImp") @Scope("singleton") public class userDaoImp implements userdao { public void save() { System.out.println("save"); } }
結果
在這裏順便給你們複習複習singleton與prototype的區別吧
singleton
Bean的實例化個數:1個
Bean的實例化時機:當Spring核心配置文件被加載時
Bean的生命週期:
對象建立:當應用加載時對象建立
對象運行:只要容器在,對象就一直活着
對象銷燬:當應用卸載,容器銷燬時
prototype:在使用getBean方法的時候建立bean
prototype
Bean的實例化格式:多個
Bean的實例化時機:當調用getBean()方法時,實例化Bean
對象建立:當使用對象時,建立新的對象實例
對象運行:只要對象在使用中,對象就一直存在
對象銷燬:對象長時間不使用,就會被java的垃圾回收機制回收
初始化方法和銷燬方法
初始化方法
@PostConstract
@PostConstruct public void constract(){ System.out.println("初始化方法"); }
銷燬方法
@PostDestroy
@PreDestroy public void destroy(){ System.out.println("在對象銷燬前執行"); }
@Value()進行注入
package com.pjh.dao; import com.pjh.dao.Imp.userdao; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Component("userDaoImp") @Scope("singleton") public class userDaoImp implements userdao { public void save() { System.out.println("save"); System.out.println("讀取配置文件:"+one); System.out.println("普通類型:"+a); } @Value("${one.one}") private String one; @Value("4") private String a; }
配置文件信息
one.one=1
applicationContext中添加的內容
<context:property-placeholder location="classpath*:one.properties"/>
測試代碼
@Test public void test(){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); userdao userdao =(userdao) classPathXmlApplicationContext.getBean("userDaoImp"); userdao.save(); }
結果
使用上面的註解還不能夠所有替代xml配置文件,還須要使用註解替代的配置以下
非自定義的Bean的配置:
加載properties文件的配置:<context:property-placeholder>
註解掃描的配置:
context:component-scan
引入其餘文件:
@Configuration 用於指定當前類是一個Spring配置類,建立容器時會從該類上加載註解,該類不能是匿名類與final類
@ComponentScan 用於指定Spring在初始化容器的時候要掃描包
做用與Spring中的此代碼相同:context:component-scan
@Bean 使用方法,將該方法的返回值返回到容器中
@Import 用於導入其餘配置類
@PropertySource 用於加載properties文件中的配置
案例
核心配置類
package com.pjh.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.stereotype.Component; /*標誌該類是核心配置類*/ @Configuration /*掃描包*/ @Component("com/pjh") /*導入其餘配置類*/ @Import(DataSourceConfig.class) public class Springconfig { }
副配置類
package com.pjh.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; import java.beans.PropertyVetoException; /*加載配置文件*/ @PropertySource("classpath:jdbc.properties") public class DataSourceConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /*Spring會將當前方法的返回值以指定名稱存儲到Spring容器中*/ @Bean("dataSource") public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } }
測試函數
@Test public void test() throws SQLException { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Springconfig.class); DataSource bean = (DataSource)applicationContext.getBean("dataSource"); Connection connection = bean.getConnection(); System.out.println(connection); }
結果
成功建立connection鏈接
爲何使用Spring集成junit?
在測試類中每一個類都要寫下面的兩行代碼
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Springconfig.class); DataSource bean = (DataSource)applicationContext.getBean("dataSource");
這兩行代碼的做用是獲取容器,不寫的話報空指針異常
爲了讓咱們測試的時候不用進行反覆的寫上述兩行的操做,咱們使用Spring來集成junit,用springjunit來建立spring容器,
咱們只需將配置文件的名稱告訴他們便可,將須要的bean直接在容器中進行注入
Spring集成junit的步驟
須要導入的jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency>