spring小结-IoC--AOP

Spring简介

百度百科:https://baike.baidu.com/item/spring/85061

Spring核心作用

解耦

jar包

英文官网:https://spring.io/projects/spring-framework

GA:为官方推荐版本

搭建简单的spring框架jar包

核心包

  • spring-beans-4.2.1.RELEASE.jar
  • spring-core-4.2.1.RELEASE.jar
  • spring-context-4.2.1.RELEASE.jar
  • spring-expression-4.2.1.RELEASE.jar
  • spring-aop-4.2.1.RELEASE.jar
  • spring-jdbc-4.2.1.RELEASE.jar
  • spring-tx-4.2.1.RELEASE.jar

依赖包

  •            com.springsource.org.jboss.logging-2.0.5.GA.jar
  •            mysql-connector-java-5.1.13-bin.jar(jdbc驱动)
  •            com.springsource.org.apache.log4j-1.2.15.jar(不必须)

IOC配置文件

官方推荐名字为:application.xml

约束

约束查找页面:https://pan.baidu.com/s/1eQkjnMMQXdHX5bshVXlUiQ

<?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:aop="http://www.springframework.org/schema/aop"

	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd

        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd

        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>

配置文件创建一个对象并赋值

  • 自定义类属性
<!-- 创建一个名字为stockService的对象 -->
<bean id="stockService" class="com.woniu.service.impl.StockServiceImpl">
    <!-- 该对象下有属性,名字分别为stockDao -->
    <!-- ref:这个属性值为一个对象,引用于stockDao这个名字的对象 -->
    <property name="stockDao" ref="stockDao" />
</bean>
<!-- 创建一个名字为stockDao的对象 -->
<bean id="stockDao" class="com.woniu.dao.impl.StockDaoImpl" />
  • Map
<property name="map">
	<map>
		<entry key="str1" value-ref="sutdent1" />
		<entry key="str2" value-ref="sutdent2" />
	</map>
</property>
  • Array
<property name="strs">
	<array>
		<value>aaa</value>
		<value>bbb</value>
	</array>
</property>
  •  List
<property name="list">
	<list>
		<ref bean="sutdent1"/>
		<ref bean="sutdent2"/>
	</list>
</property>
  • properties
<property name="pros">
	<props>
		<prop key="key1">001</prop>
		<prop key="key2">002</prop>
	</props>
</property>
  • 自动注入

  • 根据名称
<bean id="student" class="com.woniu.Student" autowire="byName">
	<property name="id" value="1" />
	<property name="name" value="张三" />
</bean>
<bean id="school" class="com.woniuxy.di02.School">
	<property name="name" value="学校" />
</bean>
  • 根据类型

当使用按类型自动注入时,不能有同类的bean,以及子父类关系的bean 

<bean id="student" class="com.woniuxy.di03.Student" autowire="byType">
	<property name="id" value="1" />
	<property name="name" value="张三" />
</bean>
<bean id="school" class="com.woniuxy.di03.School">
	<property name="name" value="父学校" />
</bean>
<bean id="superSchool" class="com.woniuxy.di03.SuperSchool">
	<property name="name" value="子学校" />
</bean>

注解形式创建一个对象并赋值

使用注解需要使用aop的jar包,以及约束

@Component("school")
public class School {
	@Value("学校")
	private String name;
	public School(String name) {
		super();
		this.name = name;
	}
	public School() {
		super();
	}
}

@Component("student")
public class Student {
	@Value("1")
	private int id;
	@Value("张三")
	private String name;
	@Resource
	private School school;
}
//配置文件,配置扫描
//	com.woniuxy.di01      扫描当前包及其字表
//	com.woniuxy.di01.*    扫描当前包的子表
<context:component-scan base-package="com.woniuxy.di04" />

还有三个注解的作用和@Componet是一样的,他们用在分层项目中,带表每层的bean

@Repository          在DAO层使用

@Service                     在Service层使用

@Controller          在Controller层使用

使用内置jdbc连接数据库

  • 配置文件

<!-- 连接jdbc四大参数文件 -->
<context:property-placeholder location="classpath:mysqljdbc.properties"/>
<!-- 创建对象 -->
<bean id="studentService" class="com.woniu.service.impl.StudentServiceImpl">
	<property name="studentDao" ref="studentDao" />
</bean>
<bean id="studentDao" class="com.woniu.dao.impl.StudentDaoImpl">
	<property name="dataSource" ref="dataSource" />
</bean>
<!--设置连接池-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	<property name="driverClassName" value="${jdbc.driver}"/>
	<property name="url" value="${jdbc.url}" />
	<property name="username" value="${jdbc.username}" />
	<property name="password" value="${jdbc.password}" />
</bean>

AOP

AOP是一种编程思想,Spring框架实现了这种思想,其他框架也可以实现。Spring的实现不好,

AspectJ框架对AOP的实现更好。Spring框架提供对AspectJ的整合支持。

直接使用Spring内置的AOP实现

       缺点:使用复杂:要实现切面织入,必须实现特定的接口,配置复杂

       7个基础包+aop联盟包(规范,接口)+spring-aop.jar

使用AspectJ实现

       7个基础包+aop联盟包(规范,接口)+spring-aop.jar+aspectjs.jar+spring-aspectj.jar(spring对aspectj的整合包)

  • 注解实现

execution设置切入点表达式指定切面的织入给哪些方法

  • 前置通知 Before
@Component("myAspect")
@Aspect
public class MyAspect {
	@Before("execution(* *..SomeService.do*(..))")
	public void befor(){
		System.out.println("前置增强");
	}
}
  • 后置通知 AfterReturning
@Component("myAspect")
@Aspect
public class MyAspect {
	@AfterReturning("execution(* *..SomeService.do*(..))")
	public void AfterReturning(){
		System.out.println("后置增强");
	}
//returning的值与方法参数引用名一致
	@AfterReturning(value="execution(* *..SomeService.doAther(..))",returning="result")
	public void AfterReturning(Object result){
		System.out.println("后置增强中操作方法返回值,但不修改方法返回值");
		System.out.println("后置增强中操作的返回值:"+result.toString().toUpperCase());
	}
}
  • 环绕通知 Around
@Component("myAspect")
@Aspect
public class MyAspect {
	@Around("execution(* *..SomeService.do*(..))")
	public Object befor(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("环绕前置通知");
		Object obj = pjp.proceed();
		System.out.println("环绕后置通知");
		if(obj!=null && obj.getClass().getName().equals("java.lang.String")){
//环绕通知可以修改方法的返回值
			return obj.toString().toUpperCase();
		}
		return obj;
	}
}
  • 异常通知 AfterThrowing

根据方法中异常类型,触发该异常类型,以及异常类型父类的方法

@Component("myAspect")
@Aspect
public class MyAspect {
	@AfterThrowing(value="execution(* *..SomeService.test*(..))",throwing="ex")
	public void AfterThrowing(Exception ex) {
		System.out.println("Exception异常通知,捕获异常:"+ex);
	}
	@AfterThrowing(value="execution(* *..SomeService.test*(..))",throwing="ex")
	public void AfterThrowing(NullPointerException ex) {
		System.out.println("NullPointerException异常通知,捕获异常:"+ex);
	}
	@AfterThrowing(value="execution(* *..SomeService.test*(..))",throwing="ex")
	public void AfterThrowing(ArithmeticException ex) {
		System.out.println("ArithmeticException异常通知,捕获异常:"+ex);
	}
}

测试结果:

  • 最终通知 After

类似于try_catch_finally中finally的用法

@Component("myAspect")
@Aspect
public class MyAspect {
	@AfterThrowing(value="execution(* *..SomeService.test*(..))",throwing="ex")
	public void AfterThrowing(ArithmeticException ex) {
		System.out.println("ArithmeticException异常通知,捕获异常:"+ex);
	}
	@After("execution(* *..SomeService.*(..))")
	public void after(){
		System.out.println("最终通知");
	}
}

测试结果:

配置文件实现

  • 前置通知

<!-- 配置切入 -->
<aop:config>
	<!-- 切入点 -->
	<aop:pointcut expression="execution(* *..SomeService.do*(..))" 
		id="pointcutdo"/>
	<!-- 切面 -->
	<aop:aspect ref="myAspect">
        <-- 设置通知类型 before前置通知 -->
		<aop:before method="befor" pointcut-ref="pointcutdo"/>
	</aop:aspect>
</aop:config>
  • 后置通知

<aop:config>
	<aop:pointcut expression="execution(* *..SomeService.doSome(..))" id="ponintcutdosome"/>
	<aop:pointcut expression="execution(* *..SomeService.doAther(..))" id="ponintcutdoather"/>
	<aop:aspect ref="myAspect">
		<aop:after-returning method="AfterReturning" pointcut-ref="ponintcutdosome" />
		<aop:after-returning method="AfterReturning(java.lang.Object)" 
			    pointcut-ref="ponintcutdoather" returning="result"/>
	</aop:aspect>
</aop:config>
  • 环绕通知

<aop:config>
	<aop:pointcut expression="execution(* *..SomeService.doSome(..))"                 
             id="ponintcutdosome"/>
	<aop:pointcut expression="execution(* *..SomeService.doAther(..))"     
             id="ponintcutdoather"/>
	<aop:aspect ref="myAspect">
		<aop:around method="around(org.aspectj.lang.ProceedingJoinPoint)" 
                      pointcut-ref="ponintcutdosome" />
		<aop:around method="around(org.aspectj.lang.ProceedingJoinPoint)" 
                      pointcut-ref="ponintcutdoather" />
	</aop:aspect>
</aop:config>

事务管理

aop联盟包, spring-aop.jar

出现异常类型:

配置文件实现

<!-- 配置事务管理器 -->
<bean id="transactionManager"
	  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<proper ty name="dataSource" ref="dataSource"/>
</bean>
<!-- 注册事务代理类,完成事务织入-->
<bean id="proxy" 	
	  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
	<property name="transactionManager" ref="transactionManager" />
	<property name="target" ref="stockService"/>
	<property name="transactionAttributes" >
		<props>
		<!-- spring对运行时异常和编译异常两个异常类型处理机制不同
			运行时异常默认回滚,编译异常默认提交。
			-Exception:设置编译异常回滚
			+RuntimeException:设置运行时异常提交
		 -->
			<prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
			<prop key="buy*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
		</props> 
	</property>
</bean> 

缺点:必须使用代理类对象

public class MyTest {
	StockService stockService; 
	@Before
	public void before(){
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		stockService = (StockService) ac.getBean("proxy");
	}

注解实现

jar包:spring-tx

配置文件

<!-- 设置自动查找 -->
<tx:annotation-driven/>

织入

	@Override
	@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
	public void buyStock(String aname, double balance, String sname, int count) {
		accountDao.updateAccount(aname, balance);
		if(true){
			throw new RuntimeException();
		}
		stockDao.updateStock(sname, count);
	}

可以直接使用目标类对象

public class MyTest {
	StockService stockService; 
	@Before
	public void before(){
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		stockService = (StockService) ac.getBean("stockService");
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值