1.Spring簡介
2.IOC 控制反轉
3.IOC創建對象的方式
4.Spring配置
5.屬性注入以bean的作用域
6.自動裝配
7.註解開發
8.Java方式配置Spring
1.Spring簡介
簡單的說spring是一個輕量級的控制反轉(IOC) 和麪向切面編程(AOP)的框架!是程序員的春天,是軟件行業的春天。
- 由Rod Johnson創建。它是爲了解決企業應用開發的複雜性而創建的。Rod Johnson ,Spring Framework創始人,著名作者。悉尼大學音樂學博士。
- 2002,首次推出了Spring框架的雛形:interface21框架!
- Spring框架即以interface21框架爲基礎,經過重新設計,並不斷豐富其內涵,於*2004年3月24日,*發佈了1.0正式版。
三個重要的網站:
官網:https://spring.io/projects/spring-framework#overview
官方下載地址: http://repo.spring.io/release/org/springframework/spring
GitHub:https://github.com/spring-projects/spring-framework
1.1 優點
- 開源的免費的框架(容器)!
- 輕量級的、非入侵式的框架!
- 控制反轉(IOC) , 面向切面編程(AOP)!
- 支持事務的處理,對框架整合的支持!
1.2 組成
核心容器
提供了依賴注入(DependencyInjection)特徵來實現容器對Bean的管理。
應用上下文(Context)模塊
上下文模塊使它成爲一個框架,這個模塊提供了許多企業服務,例如電子郵件、JNDI訪問、EJB集成、遠程以及時序調度(scheduling)服務
Spring的AOP模塊
提供了對面向切面編程的豐富支持。
JDBC抽象和DAO模塊
Spring的JDBC和DAO模塊抽取取得連接、創建語句、處理結果集,關閉連接這些重複代碼,使數據庫訪問代碼乾淨簡潔,並且可以防止因關閉數據庫資源失敗而引起的問題。
對象/關係映射集成模塊
爲幾種流行的ORM框架提供了集成方案。
Spring的Web模塊
提供了一個適合於Web應用的上下文,它也提供了Spring和其它Web框架的集成。
Spring的MVC框架
Spring的MVC框架使用IoC對控制邏輯和業務對象提供了完全的分離。
現代化的Java開發!就是基於Spring的開發!,他的官網介紹就是構建一切,協調一切,連接一切。
2.IOC
控制反轉IoC(Inversion of Control),是一種設計思想,DI(依賴注入)是實現IoC的一種方法,所謂控制反轉就是:獲得依賴對象的方式反轉了。
採用XML方式配置Bean的時候,Bean的定義信息是和實現分離的,而採用註解的方式可以把兩者合爲一體,Bean的定義信息直接以註解的形式定義在實現類中,從而達到了零配置的目的。
控制反轉是一種通過描述(XML或註解)並通過第三方去生產或獲取特定對象的方式。在Spring中實現控制反轉的是IoC容器,其實現方法是依賴注入(Dependency Injection,DI)。
2.1 IOC實現
mapper接口類
public interface UserMapper {
public void getUser();
}
mapper實現類
public class UserMapperImpl implements UserMapper{
public void getUser() {
System.out.println("11111");
}
}
service接口類
public interface UserService {
public void getUser();
}
service實現類
public class UserServiceImpl implements UserService {
private UserMapper userMapper = new UserMapperImpl();
public void getUser() {
}
}
測試
public class test {
@Test
public void test(){
Service service = new ServiceImpl();
service.getUser();
}
}
增加mapper實現類
public class UserMapperSqlImpl implements UserMapper {
public void getUser() {
System.out.println("sql");
}
}
用新的實現類,修改service裏的實現類就好,
public class ServiceImpl implements Service {
private UserMapper userMapper = new UserMapperSqlImpl();
public void getUser() {
mapper.getUser();
}
}
在增加一個mapper實現類
public class UserOracleImpl implements UserMapper {
public void getUser() {
System.out.println("oracle");
}
}
要實現這個,依舊需要在service裏修改實現,這樣在代碼要求非常多的情況下,每次都需要大量的改動,傳統new對象的邏輯開發,原來是程序員操作的,現在
用set方法!對外提供接口,程序不用管理實現,主動權交給用戶,自己set調用dao層,不是寫死程序,而是對外提供接口面向接口編程,程序不用管理,只需要提供接口。
在用戶實現類增加set方法
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public void getUser() {
}
}
測試類增加了用戶操作權限
public class test {
@Test
public void test(){
//UserMapperImpl userMapper = new UserMapperImpl();
// UserMapperSqlImpl userMapper = new UserMapperSqlImpl();
UserOracleImpl userMapper = new UserOracleImpl();
//用戶多了可以自己操作的權限
UserServiceImpl service = new UserServiceImpl();
service.setUserMapper(userMapper);
service.getUser();
}
}
解耦,這就是IOC的原型
2.2 Hello
一共就三步1.導入依賴2.編寫配置文件3.註冊bean
1.導入依賴
maven中導入依賴的時候,會幫我們自動下載相關的依賴
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
2.編寫配置文件
<?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">
<!--bean就是java對象 , 由Spring創建和管理-->
<bean id="hello" class="com.yang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
</beans>
3.註冊bean
public class test {
@Test
public void testHelloSpring(){
//解析xml文件 , 生成管理相應的Bean對象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//getBean : 參數即爲spring配置文件中bean的id
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
}
這個過程就叫控制反轉 :
控制 : 誰來控制對象的創建 , 傳統應用程序的對象是由程序本身控制創建的 , 使用Spring後 , 對象是由Spring來創建的 .
反轉 : 程序本身不創建對象 , 而變成被動的接收對象 .
依賴注入 : 就是利用set方法來進行注入的.
IOC是一種編程思想 , 由主動的編程變成被動的接收 .
3.IOC創建對象的方式
3.1 無參構造
set方法 p命名注入 默認方式
配置文件
<bean id="user" class="com.yang.pojo.User">
<property name="name" value="Spring"/>
</bean>
bean註冊
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
User user = (User) context.getBean("user");
user.show();
}
在配置文件加載的時候,容器中管理的對象就已經初始化了!
3.2 有參構造
構造器注入 c命名注入
1.參數名賦值 普通的注入方式
<bean id="user" class="com.yang.pojo.User">
<constructor-arg name="name" value="yyy"/>
</bean>
2.類型
當參數只有一個時,可以根據類型來;當有多個參數且類型不一致時,不好用
<bean id="user" class="com.yang.pojo.User">
<constructor-arg type="java.lang.String" value="liuyangyang"/>
</bean>
3.小標賦值
第一個參數的index從0開始
<bean id="user" class="com.yang.pojo.User">
<constructor-arg index="0" value="yangyang"/>
</bean>
測試:
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
User user = (User) context.getBean("user");
user.show();
}
4.Spring配置
4.1 alias別名
<!--別名,如果添加了別名,我們也可以使用別名獲取到這個對象-->
<alias name="user" alias="userNew"/>
4.2 bean和beans
<!--
id : bean 的唯一標識符,也就是相當於我們學的對象名
class : bean 對象所對應的全限定名 : 包名 + 類型
name :也是別名,而且name 可以同時取多個別名
-->
<bean id="user" class="com.yang.pojo.User" name="user2 u2,u3;u4">
<property name="name" value="洋洋"/>
</bean>
4.3 import
一般用於團隊開發使用,他可以將多個配置文件,導入合併爲一個
<import resource="st.xml"/>
<import resource="user.xml"/>
5.屬性注入以bean的作用域
5.1 屬性注入
依賴注入:Set注入!
- 依賴:bean對象的創建依賴於容器!
- 注入: bean對象中的所有屬性,由容器來注入!
複雜實體類
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
測試對象
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> list;
private Map<String,String> map;
private Set<String> set;
private String wife ;// null
private Properties info;
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public void setBooks(String[] books) {
this.books = books;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setWife(String wife) {
this.wife = wife;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.getAddress() +
", books=" + Arrays.toString(books) +
", list=" + list +
", map=" + map +
", set=" + set +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
xml配置
全局xml :學生xml需要註冊到全局xml中
<import resource="st.xml"/>
學生類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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="addr" class="com.yang.pojo.Address">
<property name="address" value="西安"/>
</bean>
<bean id="student" class="com.yang.pojo.Student">
<!--第一種,普通值注入,value-->
<property name="name" value="洋洋"/>
<property name="address" ref="addr"/>
<!--數組-->
<property name="books">
<array>
<value>紅樓夢</value>
<value>西遊記</value>
<value>水滸傳</value>
<value>三國演義</value>
</array>
</property>
<!--List-->
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<!--Map-->
<property name="map">
<map>
<entry key="k1" value="v1"/>
<entry key="k2" value="v2"/>
</map>
</property>
<!--Set-->
<property name="set">
<set>
<value>LOL</value>
<value>COC</value>
<value>BOB</value>
</set>
</property>
<!--null值注入-->
<property name="wife">
<null/>
</property>
<!--Properties 配置類-->
<property name="info">
<props>
<prop key="id">100</prop>
<prop key="sex">girl</prop>
<prop key="name">小明</prop>
</props>
</property>
</bean>
</beans>
測試類
@Test
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
Student student = (Student)context.getBean("student");
System.out.println(student.toString());
}
}
5.2 bean的作用域
1.singletion模式中 測試兩次getbean的hashcode值是否一樣
@Test
//屬性注入
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
Student student = (Student)context.getBean("student");
Student student2 = (Student)context.getBean("student");
System.out.println(student.hashCode());
System.out.println(student2.hashCode());
}
2.prototype模式中,測試兩次getbean的hashcode值是否一樣
6.自動裝配
6.1測試
entity包下三個實體類
public class Cat {
public void shout(){
System.out.println("miao~");
}
}
public class Dog {
public void shout(){
System.out.println("wang~");
}
}
public class User {
private String name;
private Cat cat;
private Dog dog;
public void setName(String name) {
this.name = name;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public String getName() {
return name;
}
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", cat=" + cat + ", dog=" + dog + '}';
}
}
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.yang.entity.Dog"/>
<bean id="cat" class="com.yang.entity.Cat"/>
<bean id="user" class="com.yang.entity.User" autowire="byName">
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
<property name="name" value="yangyang"/>
</bean>
</beans>
測試:
@Test
//5.自動裝配
public void test5(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("====================");
User user = (User)context.getBean("user");
System.out.println(user);
user.getCat().shout();
user.getDog().shout();
}
6.2自動裝配
ByName
byName: 會自動在容器上下文中查找,和自己對象set方法後面的值對應的 bean!
<bean id="dog" class="com.yang.entity.Dog"/>
<bean id="cat" class="com.yang.entity.Cat"/>
<bean id="user" class="com.yang.entity.User" autowire="byName">
<!--<property name="cat" ref="cat"/>-->
<!--<property name="dog" ref="dog"/>-->
<property name="name" value="yangyang"/>
</bean>
測試結果:
錯誤情況:
ByType
<bean id="dog" class="com.yang.entity.Dog"/>
<bean id="cat" class="com.yang.entity.Cat"/>
<!--<bean id="cat2" class="com.yang.entity.Cat"/>-->
<bean id="user" class="com.yang.entity.User" autowire="byType">
<property name="name" value="yangyang"/>
</bean>
會自動在容器上下文中查找,和自己對象屬性類型相同的bean!需要保證所有bean的class唯一,並且這個bean需要和自動注入的屬性的類型一致!
錯誤情況:
但是在開發中一般使用註解自動裝配!
6.3註解自動裝配
爲了使用註解,使用新的約束文件
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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.增加 xmlns:context="http://www.springframework.org/schema/context"
2. http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
3.配置註解支持 <context:annotation-config/>
-->
<context:annotation-config/>
</beans>
@Autowired
public class People {
//如果顯示定義了Autowired的required屬性爲false,說明這個對象可以爲null,否則不允許爲空
@Autowired(required = false)
private Cat cat;
@Autowired
private Dog dog;
private String name;
}
@Resource註解
public class People {
private String name;
@Autowired(required = false) //表示允許對象爲null ,默認是true
private Cat cat;
@Resource //也可以通過這個
private Dog dog;
}
小結:
@Resource 和@ Autowired 的區別:
- 都是用來自動裝配的,都可以放在屬性字段上
- @ Autowired 通過byType的方式實現,而且必須要求這個對象存在! 【常用】
- @ Resource 默認通過byname的方式實現,如果找不到名字,則通過byType實現!如果兩個都找不到的情況下,就報錯! 【常用】
- 執行順序不同:@ Autowired 通過byType的方式實現。@ Resource 默認通過byname的方式實現。
7.註解開發
1.必須要有aop的包
2.context約束
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.yang.pojo"/>
</beans>
3.bean屬性注入
可以放在字段屬性上,可以放在方法上,不過一般放在屬性上。
@Component("user")
//相當於<bean id=user/>
public class User {
//public String name = "liuyang";
@Value("LIUYANG")
public String name;
//相當於 <property name="name" value="LIUYANG"/>
@Value("LIUYANG2")
public void setName(String name) {
this.name = name;
}
}
4.component的三個等價註解
我們在web開發中,會按照mvc三層架構分層!
- dao 【@Repository】
- service 【@Service】
- controller 【@Controller】
這四個註解功能都是一樣的,都是代表將某個類註冊到Spring中,裝配Bean
5.小結
xml 與 註解:
- xml 更加萬能,適用於任何場合!維護簡單方便
- 註解 不是自己類使用不了,維護相對複雜!
xml 與 註解最佳實踐:
- xml 用來管理bean;
- 註解只負責完成屬性的注入;
- 我們在使用的過程中,只需要注意一個問題:必須讓註解生效,就需要開啓註解的支持
8.Java方式配置Spring
1.實體類
@Component //說明這個類被Spring接管了,註冊到了容器中
public class Dog {
@Value("小黑")//也可以
private String name;
}
2.配置類
@Configuration //代表這個類是配置類
public class myapplication {
@Bean //返回一個bean id=方法名 class=具體返回對象
public Dog dog(){
return new Dog();
}
}
3.測試類
@Test
public void test7(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(myapplication.class);
Dog dog = (Dog) context.getBean("dog");
System.out.println(dog.name);
}
4.將兩個配置類聯繫在一起
- 一個新的配置類:
@Configuration
public class myconfiguration {
}
- 將兩個配置類聯繫在一起:
@Import(myconfiguration.class)
@Configuration //代表這個類是配置類
@Import(myconfiguration.class)
public class myapplication {
@Bean //返回一個bean id=方法名 class=具體返回對象
public Dog dog(){
return new Dog();
}
}
但是傳統的開發框架還是用xml居多。