Spring框架之IoC和AOP
Spring框架简介:
2003年2月,Spring框架正式成为一个开源项目,并发布于SourceForge中。致力于Java EE应用的各种解决方案,而并不是仅仅专注于某一层的方案,是企业应用开发的“一站式”选择。贯穿表现层,业务层,持久层,并不取代已有的框架,而是以高度的开放性与它们无缝整合。
注:首先通过Spring官网的地址http://repo.spring.io/replease/org/springframework/spring/下载所需版本的spring资源。
Spring IoC:
Ioc:控制反转,也称为依赖注入,是面向对象的一种设计理念,用来降低程序代码之间的耦合度。
控制反转(依赖注入):容器(如Spring)负责把组件所依赖的具体对象注入(赋值)给组件,从而避免以硬编码的方式耦合在一起。
使用Ioc注入:
导入所需jar包,创建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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
"> </beans>
1.设值注入:
<bean id = "helloSpring" class="cn.demo.HelloSpring">
<property name="str" value="Spring"></property>
</bean>
id:为其指定一个用来访问的唯一名称,如果想指定更多的别名,可以通过name属性,用逗号,分号,空格进行分隔。
class:要注入的类的完全限定名。
property:
name:属性的setter的方法名,所以使用设值注入必须提供setter方法。
value:赋给属性的值。
2.构造注入:使用构造方法进行赋值。
<bean id="user" class="cn.bdqn.pojo.User">
<constructor-arg index="0" name="id" value="1" type="integer"></constructor-arg>
<constructor-arg index="1" name="name" value="Spring"></constructor-arg>
</bean>
constructor-arg:表示构造方法的一个参数,使用时不区分顺序。
index:参数的下标。(下标从0开始)
name:参数的名称。
value:赋予参数的值。
type:参数的类型。
使用时,无需全部指定以上属性。根据需求选择属性进行注入。
3.使用p命名空间实现属性注入:
<bean id="userDao" class="cn.dao.imp.UserDaoImp"></bean>
<bean id="user" class="cn.pojo.User" p:id="1" p:name="Spring" p:dao-ref="userDao"></bean>
p:属性名 = "属性值"
p:属性名-ref = "Bean的id"
使用p命名空间实现注入,也是通过属性的setter方法进行注入。必须提供该属性的setter方法。
测试注入的结果:(编写测试类)
package cn.test; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.bdqn.pojo.User;
import cn.bdqn.service.IUserService;
import cn.bdqn.service.imp.UserServiceImp; public class test {
public static void main(String[] args) {
ApplicationContext c = new ClassPathXmlApplicationContext("app.xml");//读取Spring核心配置文件
User user = (User) c.getBean("user");//通过bean的id获取该类的实例对象
//输出类注入的属性值。例:user.getName();//读取user类中name的值。
}
}
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)
singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。
prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。
Spring bean 默认是单例模式。可以通过 scope="prototype" 修改为多例模式。
<bean id="user" class="cn.pojo.User" scope="prototype">
注入不同的数据类型:
1.注入直接量(基本数据类型、字符串):
对于基本数据类型,及其包装类、字符串,除了可以使用value属性,还可以通过<value>子元素进行注入。
<property name = "name">
<value>张三</value>
</property>
如果属性值中包含了XML中的特殊字符(&、<、>、"、')则注入时需要处理:
1.使用<[!CDATA[]]>标记
<property name = "name">
<value><![CDATA[P&G]]></value>
</property>
2.把特殊字符替换为实体引用。
1 <property name = "name">
2 <value>P&G</value>
3 </property>
XML预定的实体引用:
< :&It; > :> &:& ':' " :"
注:XML中仅有 < 和 & 是非法的,其他三个是合法的,但是替换为实体引用是个好习惯。
2.引用其他Bean组件:
Spring中定义的Bean可以相互引用,从而建立依赖关系,除了使用ref属性,还可以通过<ref>子元素实现。
<property name = "dao">
<!-- 引用id为userDao的对象为userService的dao属性赋值 -->
<ref bean = "userDao">
</property>
<property name = "dao">
<!-- 引用id为userDao的对象为userService的dao属性赋值 -->
<ref local= "userDao">
</property>
local属性和bean属性的用法几乎一致,都是用来指定要引用Bean的id。区别在于,Spring配置文件是可以拆分多个的。使用local属性只能在同一个配置文件中检索id,而使用bean属性可以在其他配置文件中检索bean的id。
3.使用内部Bean:
如果一个Bean组仅在一处需要使用,可以把它定义为内部Bean。
<!-- 为userService的dao属性赋值,调用的是serDao方法 -->
<property name = "dao">
<!-- 定义userDao对象(这个userDaoImp只能被这个userService使用,无法被其他的Bean调用) -->
<bean class="dao.imp.UserDaoImp"/>
</property>
4.注入集合类型的属性:
1.注List或者数组类型的属性,可以使用<list>标签注入。
<property name = "list">
<list>
<!-- 定义list或数组中的元素 -->
<value>集合1</value>
<value>集合2</value>
</list>
</property>
注:list标签中可以使用value、ref等标签进行注入集合元素,甚至是一个list标签。
2.对于set,可以使用set标签进行注入。
<property name = "set">
<set>
<!-- 定义set中的元素 -->
<value>集合1</value>
<value>集合2</value>
</set>
</property>
注:set标签中可以使用value、ref等标签进行注入集合元素。
3.对于Map类型的属性。
<property name = "map">
<map>
<!-- 定义map中的键值对 -->
<entry>
<key><value>map的键1</value></key>
<value>map的值1</value>
</entry> <entry>
<key><value>map的键2</value></key>
<value>map的值2</value>
</entry>
</map>
</property>
注:如果map中的键或者值是Bean对象,可以把上述代码中的value换成ref。
4.对于Properties类型的属性。
<property name = "prop">
<props>
<!-- 定义Properties中的元素 -->
<prop key = "键1">值1</prop>
<prop key = "键2">值2</prop>
</props>
</property>
注:Properties中的键和值通常都是字符串类型。
5.注入null和空字符串值
<!-- 注入空字符串值 -->
<property name = "id"><value></value></property> <!-- 注入null值 -->
<property name = "name"><null/></property>
-----------------------------------------------------------------------------------------------------------------------------------------------
Spring AOP:
面向切面编程:是软件编程思想发展到一定的阶段的产物。是面向对象的有益补充。一般用于具有横切逻辑的场合,如范围控制、事务管理、性能检测等。面向切面简单来说就是在不改变源程序的基础上为代码段增加一些新的功能,对代码段进行增强处理。设计思想来源于代理设计模式。
切面(Aspect):一个模块化的横切逻辑(或横切关注点),可能会横切多个对象。
连接点(Join Point):通过连接点找到切点的位置。
增强处理(Advice):散布在系统中的公共功能。日志管理 事务管理。
切入点(Pointcut):增强的代码需要放入的位置。
目标对象(Target object):被一个或多个切面增强的对象.
AOP代理(AOP proxy):由AOP框架所创建的对象,实现执行增强处理方法等功能。
织入(Weaving):将增强处理代码连接到应用程序中的类型或对象的过程。
增强类型处理:前置增强、后置增强、环绕增强、异常抛出增强、最终增强等类型。
注:切面可以理解成由增强处理和切入点的组成,既包含了横切逻辑的定义,也包含了连接点的定义。面向切面编程主要关心两个问题,一个是在什么位置,二是执行什么功能。Spring AOP是负责实施切面的框架。即由AOP完成织入工作。
1.使用AOP进行增强处理:
1.定义增强类:
package cn.bdqn.advice; import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint; public class ServiceLoggingAdvice {
private Logger logger = Logger.getLogger(ServiceLoggingAdvice.class); //前置增强
public void before(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();//获得增强的方法名
String className = joinPoint.getTarget().getClass().getSimpleName();//获得增强的类名
logger.debug("前置增强。。。。");
} //后置增强
public void after(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();//获得增强的方法名
String className = joinPoint.getTarget().getClass().getSimpleName();//获得增强的类名
logger.debug("后置增强。。。。");
} //异常增强
public void thowing(Exception e){
logger.debug(e.getMessage());
} //最终增强
public void afterEnd(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();//获得增强的方法名
String className = joinPoint.getTarget().getClass().getSimpleName();//获得增强的类名
logger.debug("最终增强");
} //环绕增强
public Object round(ProceedingJoinPoint joinPoint){
Object result = null;
try {
logger.debug("环绕增强----前置");
result = joinPoint.proceed();
logger.debug("环绕增强---后置");
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
}
注:通过JoinPoint连接点可以获取目标方法的有关信息,如所在类,方法名,方法的访问修饰符等信息。
环绕增强方法声明ProceedingJoinPoint类型的参数,可以获取连接点的信息,方法与JoinPoint相同。是JoinPoint的子接口,其不但封装目标方法,以及目标参数,还封装了被代理的目标对象,通过它的proceed()方法可以调用真正的目标方法,从而达到对连接点的完全控制。
2.Spring配置文件进行AOP相关配置:
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
"> <!-- AOP -->
<!-- 增强类 --> <bean id="advice" class="cn.bdqn.advice.ServiceLoggingAdvice"></bean>
<aop:config>
<aop:pointcut expression="execution(* cn.bdqn.service..*.*(..))" id="point"/>
<aop:aspect ref="advice"> <!-- 前置增强 <aop:before method="before" pointcut-ref="point" /> -->
<!-- 异常抛出增强 <aop:after-throwing method="afterThrowing" pointcut-ref="point" throwing="e"/> -->
<!-- 最终增强 <aop:after method="afterEnd" pointcut-ref="point"/> -->
<!-- 后置增强 <aop:after-returning method="after" pointcut-ref="point"/> -->
<!-- 环绕增强 <aop:around method="around" pointcut-ref="point"/> -->
</aop:aspect>
</aop:config>
</beans>
1.前置增强:使用<aop:before>进行前置增强,在目标方法前执行。
2.后置增强:使用<aop:after-returning>进行后置增强,在目标方法之后执行。(如果目标方法出现异常,无论是否使用try-catch捕获,后置增强都不会执行)
3.异常抛出增强:使用<aop:after-throwing>进行异常抛出增强,在目标方法抛出异常时,织入增强代码。
4.最终增强:使用<aop:after>进行最终增强。(如果目标方法出现异常,无论是否使用try-catch捕获,最终增强都会执行)
5.环绕增强:使用<aop:round>进行环绕增强,在目标方法前后都可以织入增强处理。功能最为强大的增强处理类型,Spring把目标方法的控制权全部交给了它,环绕增强处理中,可以获取或者修改目标方法的参数,返回值,可以进行异常处理,甚至可以决定目标方法是否被执行。
注:配置切入点的标签<aop:pointcut>的expression的属性可以配置切入点的表达式:
execution是切入点的指示符。括号里是切入点的表达式,可以配置切入增强的处理方法的特征,也支持模糊查询:
1.public * addNewUser(entity.User): * 表示匹配所有类型的返回值。
2.public void *(entity.User): * 表示匹配所有的方法名。
3.public void addNewUser(..): ".." 表示所有参数个数和类型。
4.* com.service.*.*(..): 这个表达式表示匹配com.service包下的所有类的所有方法。
5.* com.service..*.*(..): 这个表达式表示匹配com.service包以及其子包下所有类的所有方法。
<aop:aspect>标签引用包含增强方法的Bean,然后通过各种增强标签进行增强处理。
method:表示增强类中的某个方法。
pointcut-ref:引入增强的切入点。
----异常增强中的 throwing属性代表异常的参数名。
Spring框架之IoC和AOP的更多相关文章
- spring框架DI(IOC)和AOP 原理及方案
http://www.blogjava.net/killme2008/archive/2007/04/20/112160.html http://www.oschina.net/code/snippe ...
- (精简)Spring框架的IoC(替代工厂类实现方法)和AOP(定义规则,约定大于配置)
Spring的核心框架主要包含两个技术,分别用来处理工厂类,以及事务处理和连接管理的. 两大核心概念 1) IoC:控制反转,在现在的开发中,如果想建立对象并设置属性,是需要先new对象,再通过se ...
- Spring框架(3)---IOC装配Bean(注解方式)
IOC装配Bean(注解方式) 上面一遍文章讲了通过xml来装配Bean,那么这篇来讲注解方式来讲装配Bean对象 注解方式需要在原先的基础上重新配置环境: (1)Component标签举例 1:导入 ...
- Spring框架之IOC(控制反转)
[TOC] 第一章Spring框架简介 IOC(控制反转)和AOP(面向方面编程)作为Spring框架的两个核心,很好地实现了解耦合.所以,简单来说,Spring是一个轻量级的控制反转(IoC)和面向 ...
- 详谈 Spring 中的 IOC 和 AOP
这篇文章主要讲 Spring 中的几个点,Spring 中的 IOC,AOP,下一篇说说 Spring 中的事务操作,注解和 XML 配置. Spring 简介 Spring 是一个开源的轻量级的企业 ...
- Spring核心思想Ioc和Aop (面试)
Spring核心思想Ioc和Aop (面试) 注意: Ioc和Aop并不是Spring提出的,在Spring之前就已经存在,Spring只是在技术层面给这两个思想做了非常好的实现. 1 Ioc 1.1 ...
- Spring框架中IoC(控制反转)的原理(转)
原文链接:Spring框架中IoC(控制反转)的原理 一.IoC的基础知识以及原理: 1.IoC理论的背景:在采用面向对象方法设计的软件系统中,底层实现都是由N个对象组成的,所有的对象通过彼此的合作, ...
- Spring框架的IOC核心功能快速入门
2. 步骤一:下载Spring框架的开发包 * 官网:http://spring.io/ * 下载地址:http://repo.springsource.org/libs-release-local/ ...
- Spring框架 之IOC容器 和AOP详解
主要分析点: 一.Spring开源框架的简介 二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置 一.S ...
随机推荐
- ToolBarTray与ToolBarPanel的区别
ToolBarTray 类:表示处理ToolBar 的布局的容器.用于ToolBar控件模板之中. e.g. <ToolBarTray> <ToolBar> <Butto ...
- Qt多线程学习-用例子来理解多线程
文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...
- Android消息机制架构和源码解析
http://wangkuiwu.github.io/2014/08/26/MessageQueue/
- SYN2136型 北斗NTP网络时间服务器
SYN2136型 北斗NTP网络时间服务器 北斗NTP网络时间服务器时间服务器使用说明视频链接: http://www.syn029.com/h-pd-109-0_310_36_-1.html 请将 ...
- ORACLE(系统表emp) 基本与深入学习
(一).首先我们先创建emp表(系统有的可以跳过往下看)没有直接复制运行即可.create table DEPT( deptno NUMBER(2) not null, dname VARCHAR2( ...
- vue数据加载等待组件
关于loading组件的. loading.vue <template> <div class="loading"> <div class=" ...
- Docker安装MySql-挂载外部数据和配置
环境 CentOS:7 Docker:1.31.1 MySql:5.7 拷贝mysql配置文件 1.首先创建mysql容器 -p : -e MYSQL\_ROOT\_PASSWORD= -d my ...
- 后端session的获取
Request的获取 第一种方法 @Autowired private HttpServletRequest request; 第二种方法 RequestAttributes requestAttri ...
- SQL Server温故系列(4):SQL 查询之集合运算 & 聚合函数
1.集合运算 1.1.并集运算 UNION 1.2.差集运算 EXCEPT 1.3.交集运算 INTERSECT 1.4.集合运算小结 2.聚合函数 2.1.求行数函数 COUNT 2.2.求和函数 ...
- python方法和函数集锦
方法的使用: 变量.方法名(参数) 函数的使用: 函数名(参数) 字符串 1.删除空白 rstrip(): 返回去掉尾部的空格后的字符串.(不改变原字符串) lstrip(): 去掉首部空格 stri ...