Spring 基础知识笔记【上】

16 篇文章 0 订阅

web Helloworld

TestDao.java

package dao;

public interface TestDao {
	public void sayHello();
}

TestDaoImpl.java

package dao;

public class TestDaoImpl implements TestDao{
	public void sayHello() {
		System.out.println("Hello asdasf");
	}
}

配置 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">
	
	<bean id="testDao" class="dao.TestDaoImpl"></bean>

</beans>

创建servlet:HelloServlet.java
其中doGet函数:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext application = request.getServletContext();
		//WebApplicationContext context = (WebApplicationContext)application.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
		WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(application);
		TestDao testDao = context.getBean("testDao",TestDao.class);
		testDao.sayHello();
	}

index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<a href="hello">hello fuck you</a>
</body>
</html>

普通helloworld用一个Junit Test

@Test
void test1() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    TestDao testDao = context.getBean("testDao",TestDao.class);
    testDao.sayHello();
}

依赖注入

依赖注入有两种方式,一种是构造方法注入,另一种是属性setter方法注入。

配置 spring-di.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">

	<bean id="book" class="dao.Book">
		<property name="isbn" value="0001"></property>
		<property name="name" value="effective java"></property>
		<property name="price" value="80.6"></property>
	</bean>
	
	<bean id="book1" class="dao.Book">
		<constructor-arg value="0002" index="0"></constructor-arg>
		<constructor-arg value="56.3" index="2"></constructor-arg>
		<constructor-arg value="python" index="1"></constructor-arg>
	</bean>
</beans>

<property>标签为 setter 注入。
<constructor-arg>标签为 构造器注入

Junit Test:

void testDi() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-di.xml");
    Book book = (Book)context.getBean("book1");
    //Book book = (Book)context.getBean("book");
    System.out.println(book);
}

使用value子标签及<![CDATA[]]>处理特殊属性值。

如果value值里有特殊字符,如:
<property name="name" value="1+1<2"></property>
这时由于value="1+1<2"会出错,应该使用<![CDATA[]]>

spring-di.xml:

<bean id="book" class="dao.Book">
    <property name="isbn" value="0001"></property>
    <property name="name">
        <value><![CDATA[1+1<2?]]></value>
    </property>
    <property name="price" value="80.6"></property>
</bean>

Junit:

@Test
void testDi() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-di.xml");
    Book book = (Book)context.getBean("book");
    System.out.println(book);
}

注入使用引用

<bean id="book" class="dao.Book">
    <property name="isbn" value="0001"></property>
    <property name="name">
        <value><![CDATA[1+1<2?]]></value>
    </property>
    <property name="price" value="80.6"></property>
    <property name="author" ref="author"></property>
</bean>

<bean id="book1" class="dao.Book">
    <constructor-arg value="0002" index="0"></constructor-arg>
    <constructor-arg value="56.3" index="2"></constructor-arg>
    <constructor-arg value="python" index="1"></constructor-arg>
    <constructor-arg ref="author" index="3"></constructor-arg>
</bean>

<bean id="author" class="dao.Author">
    <property name="name" value="Jinondo"></property>
    <property name="age" value="21"></property>
</bean>

注意里面不是 value="",而是 ref=""

也可以直接用内部类

<bean id="book" class="dao.Book">
    <property name="isbn" value="0001"></property>
    <property name="name">
        <value><![CDATA[1+1<2?]]></value>
    </property>
    <property name="price" value="80.6"></property>
    <property name="author">
        <bean class="dao.Author">
            <property name="name" value="T0wn"></property>
            <property name="age" value="18"></property>
        </bean>
    </property>
</bean>

Bean的属性为集合类型:Array, List, Set, Map

<bean id="author" class="dao.Author">
    <property name="name" value="Jinondo"></property>
    <property name="age" value="21"></property>
    <property name="interest">
        <list>
            <value>Reading</value>
            <value>Dancing</value>
        </list>
    </property>
</bean>

或者是 map 等

<map>
    <entry key="" value=""></entry>
</map>

或 value 为引用

<map>
    <entry key="" value-ref=""></entry>
</map>

还有一种办法是定义在外面
首先要有util的引用资源

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util-4.0.xsd"
	>
<util:list id="interestList">
    <value>Singing</value>
    <value>exercise</value>
</util:list>
<bean id="author" class="dao.Author">
    <property name="name" value="Jinondo"></property>
    <property name="age" value="21"></property>
    <property name="interest" ref="interestList"></property>
</bean>

bean的实例化

在面向对象的程序中,想要使用某个对象,就需要先实例化这个对象。同样,在Spring中,要想使用容器中的Bean,也需要实例化Bean。实例化Bean有三种方式,分别为构造器实例化、静态工厂方式实例化和实例工厂方式实例化(其中最常用的是构造器实例化)。

提示:在前面的例子中都是使用构造器实例化

静态工厂方法实例化

静态工厂是实例化Bean的另一种方式。该方式要求自己创建一个静态工厂的方法来创建Bean的实例。

  1. 创建 MyBean.class。成员变量为name和age
  2. 创建 MyBean2Factory.class
public class MyBean2Factory {
	public static MyBean createBean(){
        return new MyBean("Jinondo",20);
    }

}
  1. 配置 spring-create.xml
<bean id="bean1" class="dao.MyBean2Factory" factory-method="createBean">
	<property name="name" value="wdnmd"></property>
</bean>
  1. 调用测试
@Test
void testCreate() {
	ApplicationContext context = new ClassPathXmlApplicationContext("spring-create.xml");
	MyBean bean1 = (MyBean)context.getBean("bean1",MyBean.class);
	System.out.println(bean1);
}

实例工厂方式实例化

实例工厂是采用直接创建Bean实例的方式,在配置文件中,通过factory-bean属性配置一个实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。

  1. 创建 MyBean.class。成员变量为name和age
  2. 创建 MyBean3Factory.class
public class MyBean3Factory {
	public MyBean createBean(){
        return new MyBean();
    }

}
  1. 配置 spring-create.xml
<bean id="beanFactory" class="dao.MyBean3Factory"></bean>
<bean id="bean2" factory-bean="beanFactory" factory-method="createBean">
	<property name="name" value="g-dragon"></property>
	<property name="age" value="33"></property>
</bean>

4.调用测试

@Test
void testCreate() {
	ApplicationContext context = new ClassPathXmlApplicationContext("spring-create.xml");
	MyBean bean2 = (MyBean)context.getBean("bean2",MyBean.class);
	System.out.println(bean2);
}

bean 的作用域

  1. 单例 singleton (为默认形式)

    singleton 是 Spring容器默认的作用域,当 Bean 的作用域为 singleton 时,Spring 容器就只会存在一个共享的 Bean实例。singleton 作用域对于无会话状态的Bean(如 Dao 组件、Service 组件)来说,是最理想的选择。

<bean id="student" class="dao.Student" scope="singleton"></bean>

测试

@Test
void testLifecycle() {
	ApplicationContext context = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
	Student student1 = context.getBean("student",Student.class);
	Student student2 = context.getBean("student",Student.class);
	System.out.println(student1==student2);
}

结果为 true

  1. 原型 prototype

    对需要保持会话状态的 Bean(如Struts 2的 Action类)应该使用 prototype作用域。在使用 prototype作用域时,Spring容器会为每个对该 Bean的请求都创建一个新的实例。

<bean id="student" class="dao.Student" scope="prototype"></bean>

与上同一程序测试为 false

singleton: 单例的(默认值), 在整个IOC容器中只存在一个bean的对象。 而且在IOC容器对象被创建时,就创建单例的bean的对象。 后续每次通过getBean()方法获取bean对象时,返回的都是同一个对象。

prototype: 原型的,在整个IOC容器中可有多个bean的对象。在IOC容器对象被创建时, 不会创建原型的bean的对象。而是等到每次通过getBean()方法获取bean对象时,才会创建一个新的bean对象返回。


bean 的生命周期

  1. singleton作用域
    Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下,Spring能够精确的知道该Bean何时被创建,何时初始化完成,以及何时被销毁。

  2. prototype作用域
    prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。

<bean id="student" class="dao.Student" scope="singleton" init-method="init" destroy-method="destroy">
	<property name="name" value="cyt"></property>
	<property name="age" value="21"></property>
</bean>

Student.java

public void init() {
	System.out.println("init");
}

public void destroy() {
	System.out.println("destroy");
}

基于 xml 的自动装配

自动装配只针对于引用型属性,即手动装配的 ref=""

  1. 根据类型自动装配:将类型匹配的bean作为属性注入到另一个bean中。若IOC容器中有多个与目标bean类型一致的bean,Spring将无法判定哪个bean最合适该属性,所以不能执行自动装配

设有People.java 和 Address.java,People和Address为依赖关系
People有三个属性

private String id;
private String name;
private Address address;
<bean id="people" class="dao.People" autowire="byType">
	<property name="id" value="0001"></property>
	<property name="name" value="jinondo"></property>
</bean>

<bean id="address" class="dao.Address">
	<property name="province" value="GuangDong"></property>
	<property name="city" value="DG"></property>
</bean>

如果出现多个 class=“dao.Address” 的bean,byType的方式则会出错

  1. 根据名称自动装配:必须将目标bean的名称和属性名设置的完全相同。
<bean id="people" class="dao.People" autowire="byName">
	<property name="id" value="0001"></property>
	<property name="name" value="jinondo"></property>
</bean>

<bean id="address" class="dao.Address">
	<property name="province" value="GuangDong"></property>
	<property name="city" value="DG"></property>
</bean>

<bean id="address2" class="dao.Address">
	<property name="province" value="GuangDong"></property>
	<property name="city" value="ShanTou"></property>
</bean>

基于注解(Annotation)的装配

Repository,Controller,Service:

@Repository("userDaoImpl")
public class UserDaoImpl implements UserDao {

	@Override
	public void addUser() {
		System.out.println("Dao: addUser");

	}
}
@Controller
public class UserController {
	public void handleUserInput() {
		System.out.println("Controller: handle User Input");
	}
}
@Service
public class UserService {
	public void addUser() {
		System.out.println("Service: add User");
	}
}

xml 中的配置

<context:component-scan base-package="cyt"></context:component-scan>

bean id 默认为类名首字母小写,注解可以设置 bean 的 id,如@Repository("userDaoImpl")

包含与排除

排除
<context:component-scan base-package="cyt">
	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
包含:只扫描选中的 bean!

注意排除应该配合父标签,即scan标签中的 use-default-filters 属性进行使用,即设置 use-default-filters="false"

<context:component-scan base-package="cyt" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

@Autowire工作机制

引用在基于注解装配时需要在引用前加上 @Autowire 注解

  1. Controller 中有 Service 的引用
@Repository("userDaoImpl")
@Controller
public class UserController {
	
	@Autowired
	private UserService service;
	
	public void handleUserInput() {
		System.out.println("Controller: handle User Input");
		service.addUser();
	}
}
  1. Service 里有 Dao 的引用
@Service
public class UserService {
	
	@Autowired
	private UserDao dao;
	
	public void addUser() {
		System.out.println("Service: add User");
		dao.addUser();
	}
}

Junit Test 测试

@Test
void test2() {
	context = new ClassPathXmlApplicationContext("applicationContext.xml");
	UserController userController = context.getBean("userController",UserController.class);
	userController.handleUserInput();
}

由以上例子说明:@Autowired 注解对引用的装配属于 ByType 类型
如果 ByType 类型不能唯一找出一个,就会在 ByType 类型找出的多个bean基础上,进一步根据名字去找,例如 在@Repository(“userDaoImpl”) 时设置的 userDaoImpl。
如果不能按名字区别开2个或多个bean,则会出错!

@Qualifiter

@Qualifiter可以辅助@Autowire确定需要装配的Bean的id,在@Autowired找到多于两个的bean时,也可以用 @Qualifiter 直接设置要装配的 bean 的 id。

@Service
public class UserService {
	
	@Autowired
	@Qualifier("userDaoImpl")
	private UserDao dao;
	
	public void addUser() {
		System.out.println("Service: add User");
		dao.addUser();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值