spring就是個大工廠,它管理和生產對象。
我們最初是通過xml來完成DI的。
我們有個entity:
package spring_annotation.entity;
import org.springframework.stereotype.Component;
public class User {
private Integer age;
private String name;
private String from;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public User(Integer age, String name, String from) {
super();
this.age = age;
this.name = name;
this.from = from;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + ", from=" + from + "]";
}
}
有個dao:
package spring_annotation.dao;
import org.springframework.stereotype.Repository;
public class UserDao {
public void reg() {
System.out.println("UserDao's reg()");
}
}
還有service層:
package spring_annotation.service;
import org.springframework.stereotype.Service;
import spring_annotation.dao.UserDao;
public class UserServlet {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void reg() {
System.out.println("UserServlet's reg()");
userDao.reg();
}
}
隨便舉個例子。
現在我們要通過xml的配置,將這些對象交由spring管理,併爲其注入值:
在類路徑下配好spring配置文件:
<?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"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<bean id="user" class="spring_annotation.entity.User"
><property name="name" value="Lily"></property>
<property name="age" value="15"></property>
<property name="from" value="London"></property></bean>
<bean id="userDao" class="spring_annotation.dao.UserDao"></bean>
<bean id="userServlet" class="spring_annotation.service.UserServlet">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
我們用bean節點註冊bean類,id是爲了方便spring容器提取bean,class必須寫全類名。我們可以用property節點爲屬性注入值,這其實是調用了bean中的set方法。當然你可以用有參構造(constructor-arg)爲其注入值。
對於UserServlet,我們要爲其中的屬性userDao注入值,而userDao是個對象,所以我們要用ref屬性節點ref="userDao"
,由此找到id爲"userDao"的bean。
所以兩個bean之間的依賴關係也是在配置文件中做完的。
注入值的場景很多,有爲map注入值,list注入值,set注入值,還有爲Properties注入數據庫的基本鏈接信息。
還有spring動態注入,即spring El表達式(#{})。
我們寫個簡單的測試方法看看spring容器是否加載了這些bean:
@Test
public void test03() {
ClassPathXmlApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserServlet userServlet = ac.getBean("userServlet",UserServlet.class);
userServlet.reg();
ac.close();
}
測試結果:
現在看看基於註解的bean註冊吧。其實你可以想到,不管是用XML還是註解,都是用反射技術來讀取內容的。
我們要寫個配置類,它的作用相當於之前的XML配置文件:
package spring_annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import spring_annotation.entity.User;
@ComponentScan("spring_annotation")
@Configuration
public class MainConfig {
@Bean("user02")
public User user() {
return new User(12, "Jack", "New York");
}
}
這裏@Configuration
註解表明它是個配置類。
用@Bean
註解告訴容器這是要註冊的bean,bean的id默認爲方法名,也就是user,但是如果你指定value的值爲user02
,那id就爲user02
。
寫個測試類:
AnnotationConfigApplicationContext applicationContext = null;
@Before
public void loadApplicationContext() {
applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
}
@After
public void closeApplicationContext() {
applicationContext.close();
}
@Test
public void test01() {
Object user = applicationContext.getBean("user02");
System.out.println(user);
}
運行test01,我們就用id值拿到了bean:
再看配置類,它有@ComponentScan("spring_annotation")
,這是自動包掃描,比起XML中的<context:component-scan base-package="xxx"></context:component-scan>
要方便得多。
爲User類、UserDao類、UserServlet類加上基本註解後,它們也會被納進spring容器的管理。
@Repository
public class UserDao {
public void reg() {
System.out.println("UserDao's reg()");
}
}
@Component
public class User {
private Integer age;
private String name;
private String from;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public User(Integer age, String name, String from) {
super();
this.age = age;
this.name = name;
this.from = from;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + ", from=" + from + "]";
}
}
@Service
public class UserServlet {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void reg() {
System.out.println("UserServlet's reg()");
userDao.reg();
}
}
運行test02:
@Test
public void test02() {
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
我們能拿到所有定義的bean:
除了spring它自己的bean,剩餘的都是我們加了註解要求spring管理的bean。