Spring简单梳理

Spring学习笔记

author:木子六日

DAY1

spring能帮我们创建对象,对象交由spring管理,不用程序员创建,实现了程序员与对象管理之间的解耦(不用new对象了)。

导包

主要的包有五个:beans、context、core、expression再加上一个commons-logging;

配置文件

在src下创建applicationContext.xml配置文件(位置和文件名都无所谓的),导入xmlns(照抄就行了);

<?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-2.5.xsd">
	
</beans>
三种创建对象的方法

1.通过构造函数创建;

2.通过实例工厂创建;

3.通过静态工厂创建;

这里举一个具体的例子,比如有如下的People类和PeopleFactory类

package com.pojo;
/**
* People类
*/
public class People {
	private String name;
	private int age;
	private String sex;
	
	public People() {
		super();
	}
	public People(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "People [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
	
}

package com.pojo;
/**
* PeopleFactory类
*/
public class PeopleFactory {
	public People newInstance() {
		return new People("实例工厂创建",0,null);
	}
	public static People newInstance2() {
		return new People("静态工厂创建",0,null);
	}
}

如果是以前的话,按以上所写有三种办法创建一个People对象:

1.通过构造方法:

People peo = new People();

2.通过实例工厂:

PeopleFactory factory = new PeopleFactory();
People peo = factory.newInstance();

3.通过静态工厂:

People peo = PeopleFactory.newInstance2();
这三种方法在spring中的使用

工厂模式还有其他的一些模式,spring仅对实例工厂和静态工厂提供支持。

首先我们要配置之前的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-2.5.xsd">
	<!-- 
		通过构造方法创建对象
			id表示获取到对象标识
			class表示创建哪个类的对象
	 -->
	<bean id="peo" class="com.pojo.People">
		<!-- 这里面不写东西的话,默认走类的无参构造 -->
		<!-- 如果要走有参构造,如下 -->
		<constructor-arg index="0" value="木子六日"></constructor-arg>
		<constructor-arg index="1" value="24"></constructor-arg>
		<constructor-arg index="2" value=""></constructor-arg>
		<!-- 
			index表示参数位置,
			name表示参数名称,
			type表示参数类型,
			只要这三个能唯一标识出使用那个你想要的构造方法即可,三个属性不必都出现。
			value表示值,仅限于基本数据类型和字符串作为参数能使用,
			如果参数是一个对象,则需使用ref引用其他bean 
		-->
	</bean>
	
	<!-- 
		实例工厂模式创建对象:
			创建一个工厂的bean
			创建实例的bean(不需要再写class属性了,由工厂创建),
			factory-bean属性写工厂bean的id,factory-method属性写创建这个对象的方法名 
	-->
	<bean id="peoFac" class="com.pojo.PeopleFactory"></bean>
	<bean id="peo1" factory-bean="peoFac" factory-method="newInstance"></bean>
	
	<!-- 
		静态工厂模式创建对象:
			不需要创建工厂bean,直接创建对象的bean
			class写工厂的全限定路径,factory-method写创建这个对象的静态方法
	 -->
	<bean id="peo2" class="com.pojo.PeopleFactory" factory-method="newInstance2"></bean>
</beans>

写一个测试类测一下:

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.pojo.People;

public class Test {
	public static void main(String[] args) {
        //这一步是加载配置文件
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        
		//第一个参数指明了xml中bean的id,标识对象
        //第二个参数指明类(可以不写第二个参数,这样的话返回值是Object,再强转效果一样)
		
        //通过构造方法创建的对象
		People peo = ac.getBean("peo",People.class);
		System.out.println(peo);
		
		//通过实例工厂创建的对象
		People peo1 = ac.getBean("peo1",People.class);
		System.out.println(peo1);
		
		//通过静态工厂创建的对象
		People peo2 = ac.getBean("peo2",People.class);
		System.out.println(peo2);
	}
}

DAY2

spring的对象属性注入

之前说了可以通过构造方法,也可以通过set方法来做,具体如下

<!-- 如果不使用构造方法,也可以使用set方法对对象赋值 -->
<bean id="peo3" class="com.pojo.People">
    <property name="name" value="哈哈"></property>
    <property name="age" value="12"></property>
    <!-- 也可以这样写 -->
    <property name="sex">
        <value></value>
    </property>
    <!-- 如果某一属性是Set -->
    <property name="sets">
        <set>
            <value>1</value>
            <value>2</value>
            <value>3</value>
            <value>4</value>
        </set>
    </property>
    <!-- 
   如果属性是List,跟Set一样,只是把set标签换成list标签
   如果list中只有一个值,可以直接使用value属性进行赋值

   如果属性是数组,就把set标签换成array标签即可,一个值的情况
   也可以使用类似于list的简写形式	
   -->

    <!-- 如果属性是map类型,写法如下 -->
    <property name="map">
        <map>
            <entry key="a" value="b"></entry>
            <entry key="c" value="d"></entry>
            <entry key="e" value="f"></entry>
        </map>
    </property>
    <!-- 如果属性是另一个对象,就要用到DI(依赖注入) -->
    <property name="bag" ref="bag"></property>
</bean>
<!-- DI需要先在外面写好一个对象 -->
<bean id="bag" class="com.pojo.Bag">
    <property name="id" value="2"></property>
    <property name="price" value="40.6"></property>
</bean>

spring整合Mybatis(十分重要)

首先肯定要导包,除了spring的包和mybatis的包外,还需要数据库的驱动包和spring-mybatis.jar.

我们可以把mybatis.xml那个文件省掉了,舒服,在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-2.5.xsd">
	
	<!-- Spring整合mybatis -->
	
	<!-- 整合dataSource -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
		<property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;characterEncoding=UTF-8"></property>
		<property name="username" value="root"></property>
		<property name="password" value="lijingjing"></property>
	</bean>
	
	<!-- 整合生产SQLSession的工厂 -->
	<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 获取dataSource -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 整合mybatis.xml中的mappers(就是加载mapper那个作用) -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.mapper"></property>
		<property name="sqlSessionFactory" ref="factory"></property>
	</bean>
	
	<!-- 创建service层的实例 这一步跟mybatis无关 -->
	<bean id="flowerService" class="com.service.impl.FlowerServiceImpl">
		<property name="flowerMapper" ref="flowerMapper"></property>
	</bean>
</beans>

当然之前的mapper包和pojo包是不可少的,这些跟mybatis的时候写法一样。

测试代码如下:

package com.test;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.pojo.Flower;
import com.service.FlowerService;
import com.service.impl.FlowerServiceImpl;

public class Test {
	public static void main(String[] args) {
		//加载配置文件
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//		for(String str:ac.getBeanDefinitionNames()) {
//			System.out.println(str);
//		}
		FlowerService fs = ac.getBean("flowerService",FlowerServiceImpl.class);
		List<Flower> list = fs.showAll();
		for(Flower f:list) {
			System.out.println(f);
		}
	}
}


配置文件加载完成后,spring扫描了com.mapper包,之后就已经生成了flowerMapper的实现类(注意mapper.xml必须绑定接口),所以在service层就可以直接拿到flowerMapper的实现类。

service实例的代码如下:

package com.service.impl;

import java.util.List;

import com.mapper.FlowerMapper;
import com.pojo.Flower;
import com.service.FlowerService;
/**
 * 注意此类的实例化也要放到applicationContext中
 * @author 木子六日
 *
 */
public class FlowerServiceImpl implements FlowerService{
	//这个在扫描的时候被创建好了,记得要生成get和set
	private FlowerMapper flowerMapper;
	

	public FlowerMapper getFlowerMapper() {
		return flowerMapper;
	}


	public void setFlowerMapper(FlowerMapper flowerMapper) {
		this.flowerMapper = flowerMapper;
	}


	@Override
	public List<Flower> showAll() {
		return flowerMapper.selAll();
	}

}


serviceImpl拿到flowerMapper的过程是在applicationContext中完成的,通过DI获取到,

即xml中的这一句<property name="flowerMapper" ref="flowerMapper"></property>

还是把mapper.xml和绑定的接口放一下吧,如下(跟纯mybatis的时候一样的):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.FlowerMapper">
	<select id="selAll" resultType="com.pojo.Flower">
		select * from flower
	</select>
</mapper>

package com.mapper;

import java.util.List;
import com.pojo.Flower;

public interface FlowerMapper {
	public List<Flower> selAll();
}


DAY3

aop面向切面编程是spring的一个重要概念,主要目的就是给方法添加一些通知。

使用aop之前要记得导包,除了spring的aop包之外还有aopalliance.jar和aspectjweaver.jar.

schema based实现前置、后置通知

applicationContext.xml中要有写如下配置:

<!-- 注入前置通知对象 -->
<bean id="mybefore" class="com.advice.MyBeforeAdvice"></bean>
<!-- 注入后置通知对象 -->
<bean id="myafter" class="com.advice.MyAfterAdvice"></bean>
<!-- 注入切点对象 -->
<bean id="point" class="com.test.Test"></bean>
<aop:config>
    <!-- 配置切点 -->
    <!-- 
   *表示可以表示配置任意方法
   比如com.test.Test.*就是代表所有方法,
   ()表示无参,若想匹配任意类型参数,(..)
   -->
    <aop:pointcut expression="execution(* com.test.Test.printTest(..))" id="mypoint"/>
    <!-- 添加通知:schema based方式 -->
    <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
    <aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
</aop:config>

前置通知对象如下:

package com.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
 * 前置通知类
 * @author 木子六日
 *
 */
public class MyBeforeAdvice implements MethodBeforeAdvice{

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		System.out.println("我是前置通知");
		//arg0切点方法对象
		System.out.println("切点方法对象:"+arg0+"  切点方法名:"+arg0.getName());
		//arg1切点方法参数
		if(arg1!=null&&arg1.length>0) {
			System.out.println("切点方法有参数");
		}else {
			System.out.println("切点方法没有参数");
		}
		//arg2切点对象
		System.out.println("切点对象为:"+arg2);
	}
	
}


后置通知对象如下:

package com.advice;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyAfterAdvice implements AfterReturningAdvice{

	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		System.out.println("我是后置通知");
		//后三个参数与前置通知一样,arg0代表返回值
		System.out.println("返回值是:"+arg0);
	}

}


schema based实现环绕通知

与前置后置通知类似

<!-- 注入环绕通知对象 -->
<bean id="myaround" class="com.advice.MyAround"></bean>
<aop:config>
    <aop:pointcut expression="execution(* com.test.Test.printTest(..))" id="mypoint"/>
 	<aop:advisor advice-ref="myaround" pointcut-ref="mypoint"/>
</aop:config>

环绕通知对象如下:

package com.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 环绕通知
 * @author 木子六日
 *
 */
public class MyAround implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		System.out.println("我是环绕前置通知");
		Object res = arg0.proceed();//放行切点方法
		System.out.println("我是环绕后置通知");
		return res;
	}

}


Aspectj实现异常通知

xml配置如下:

<!-- 注入aspectj通知对象 -->
<bean id="mythrow" class="com.advice.MyThrowAdvice"></bean>
<aop:config>
    <!-- 添加通知:aspectj方式(此处以异常处理为例) -->
    <!-- 通过ref注入通知对象 -->
    <aop:aspect ref="mythrow">
        <aop:pointcut expression="execution(* com.test.Test.printTest2(..))" id="mypoint2"/>
        <!-- method方法名   pointcut-ref切点id   throwing方法形参名 -->
        <aop:after-throwing method="myThrow" pointcut-ref="mypoint2" throwing="e"/>
    </aop:aspect>
</aop:config>

aspectj的异常通知对象(自定义,无需实现接口)如下:

package com.advice;
/**
 * aspectj的通知类不需要继承
 * @author 木子六日
 *
 */
public class MyThrowAdvice {
	public void myThrow(Exception e) {
		System.out.println("我是抛出的异常,异常信息为:"+e.getMessage());
	}
}


DAY 4

scope属性

可设置spring容器中的对象是否为单例,在什么范围内单例,使用如下:

<!-- scope属性 -->
<!-- 
 取出spring容器中的bean时,无论取几次,都是同一个对象 
 因为默认是单例的。
 如果我们想每取一次都是一个新的对象
 可以使用scope属性,设置为prototype,默认是singleton。
 scope还能取值为request,表示一次请求内单例
 session取值表示一次会话内单例
 -->
<bean id="eye" class="com.pojo.Eye" scope="prototype">
    <property name="color" value="brown"></property>
</bean>

自动注入

此功能可以免去一些需要依赖注入的对象的注入步骤,具体使用如下:

<!-- 自动注入:autowire -->
<!-- 这是以前的标准写法,使用ref注入一个对象 -->
<bean id="peo" class="com.pojo.People">
    <property name="eye" ref="eye"></property>
</bean>

<!--使用自动注入可以这样写,通过id与该对象属性的匹配,直接注入,不再写property标签-->
<!-- 当然也可以使用byType进行注入,是通过匹配类型 -->
<bean id="peo2" class="com.pojo.People" autowire="byName">
</bean>

<!-- 我们还可以直接在beans里面配置全局默认的autowire -->
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd"
    default-autowire="byName"
    >

spring读取properties配置文件

方法如下:

<!-- spring读取属性文件 -->
<context:property-placeholder location="classpath:test.properties"/>
<bean id="me" class="com.pojo.Me">
    <property name="name" value="${ljj.name}"></property>
    <property name="age" value="${ljj.age}"></property>
    <property name="sex" value="${ljj.sex}"></property>
</bean>

当然我们需要先创建properties文件,test.properties如下:

ljj.name=ljj
ljj.sex=male
ljj.age=18

DAY5

声明式事务

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:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"     
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
    >
    <!-- 加入扫描使注解生效 -->
    <context:component-scan base-package="com.service.impl"></context:component-scan>
    <!-- 整合mybatis -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driver}"></property>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	
	<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.mapper"></property>
		<property name="sqlSessionFactoryBeanName" value="factory"></property>
	</bean>
	
	<!-- 声明式事务:spring提供的事务自动提交回滚等操作,不用手动写了 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 当然这边也可以使用自动注入,就不用再写一遍property了 -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置声明式事务 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<!-- 
				name:方法名称,支持通配符;
				readonly:是否为只读,查询建议只读,提升效率,默认为false;
			 -->
			<tx:method name="showAll" read-only="true"/>
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut expression="execution(* com.service.impl.FlowerServiceImpl.*(..))" id="mypoint"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
	</aop:config>
	

</beans>

常用注解

下面是service实体类的注解:

@Service
//service的注解,这样就不需要在xml配置bean了
public class FlowerServiceImpl implements FlowerService{
	@Resource
	//注入mapper,使用Resource注解或autowired注解,都不需要再写set get方法
	private FlowerMapper flowerMapper;
	
	@Override
	public List<Flower> showAll() {
		return flowerMapper.selAll();
	}

}


flowerMapper是何时实例化的呢?xml也没有配这个bean啊?

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="com.mapper"></property>
	<property name="sqlSessionFactoryBeanName" value="factory"></property>
</bean>

就是这个,这里会把mapper包下的对象都创建出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值