Spring框架之IOC、AOP详解
2017-01-18 10:05
525 查看
Spring 框架之IOC、AOP
spring概念
spring是项目中对象的容器.用来管理项目中的所有对象.创建对象,并维护对象间的关系AOP
整合代理技术,实现AOP思想
spring可以整合几乎任何第三方框架,作为项目中的粘合剂.
IOC&DI概念
IOC:反转控制,创建对象的方式被反转,从我们自己创建变为程序创建.DI:依赖注入,是技术,可以将依赖属性注入到对象.构造注入|set方法注入.IOC的实现需要依赖DI技术.
BeanFactory&ApplicationContext
BeanFactory接口BeanFactory是spring框架初代接口.
BeanFactory是ApplicationContext父接口.
BeanFactory是获得对象时才创建对象.
ApplicationContext接口
ApplicationContext是后期发展出的接口.
ApplicationContext的功能要更加强大.
ApplicationContext是启动时默认立刻创建容器中所有对象,获得时直接返回
AOP思想
纵向重复,横向抽取.spring封装了代理技术,通过代理技术来体现aop思想.我们使用代理体现aop时,不需要我们自己书写代理代码.spring帮我们完成.
spring框架搭建
导包
4个核心包,core、bean、context、exception2个日志包,apache.commons.loggin、apache.log4j
准备对象
创建一个类创建spring配置文件
在src目录下创建applicationContext.xml导入4个约束(schema)beans、context、tx、aop
<!--将User对象交给spring管理--> <bean name="user" class="cn.it.domain.User"></bean> <!--配置dao--> <bean name="userDao" class="cn.it.dao.impl.UserDao"></bean> <!--配置service--> <bean name="userService" class="cn.it.service.impl.UserService"> <property name="userDao" ref="userDao"></property> </bean>
配置spring容器随项目启动
原则:一个web项目启动只创建一个spring容器.操作:
方案一:将spring容器的创建放入静态代码块中.该访问属于自己手动创建容器,容器与web项目没有关联,不推荐.
方案二:spring利用监听器(ServletContext对象创建与销毁监听器)来创建容器.
<!--配置spring容器随项目启动--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--指定spring配置文件位置--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
原理:ContextLoaderListener继承了ServletContextListener,ServletContextListener监听ServletContext的创建与销毁。
代码测试
SE环境测试//1.创建spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //2.获取User对象 User user = ac.getBean("user");<
4000
/pre>
获得spring容器及容器中对象
Web环境下//1.获得Application域对象 ServletContext sc = ServletActionContext.getServletContext(); //2.调用工具方法从域中取出对象 ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc); //3.获得CustomerService us = (UserService) ac.getBean("userService");spring配置详解(xml)
基础配置
bean元素:将对象交给spring容器管理
name属性:对象的名字,spring根据该名字获得。
id属性:对象的名字,spring根据该名字获得。name属性与id属性区别: 1.id出现时间较早. 2.id属性必须符合id规范:唯一不能使用特殊字符. 3.name属性:可以重复(不推荐重复),也可以使用特殊字符.
class属性:对象的完整类名。
scope属性:决定对象的作用域,生命周期。singleton(默认值):单例,容器启动时创建单例对象,容器销毁时才销毁单例对象. prototype:原型多例,启动时不会创建,每次获得时都会创建新的对象,对象不会放入容器的管理. request:web环境下的属性,对象的生命周期为一次请求. session:web环境下的属性,对象的生命周期为一次会话.
init-method|desotory-method属性:指定对象的生命周期。init-method:指定对象的初始化方法,会在构造方法调用之后调用. destory-method:指定对象的销毁方法,会在容器销毁对象之前调用.
xml配置<bean name="user" class="cn.it.domain.User" scope="prototype" init-method="init" destory-method="destory"></bean>sping创建对象方法
静态工厂
//静态工厂 public class UserFactory{ public static User getUser(){ return new User(); } }
xml配置文件<bean name="user2" class="cn.it.factory.UserFactory" factory-method="getUser"></bean>动态工厂
//动态工厂 public class UserFactory{ public User getUser2(){ return new User(); } }
xml配置文件<bean name="userFactory" class="cn.it.factory.UserFactory"></bean> <bean name="user3" factory-bean="userFactory" factory-method="getUser2"></bean>构造方法(推荐)
<bean name="user" class="cn.it.domain.User"></bean>spring中的DI(依赖注入)
构造方法注入
constructor-arg:指定构造参数
定位属性:
name属性:参数名
index属性:指定参数在参数列表中的索引
type属性:指定参数类型
注入属性:
value属性:参数值
ref属性:注入引用类型<bean name="user" class="cn.it.domain.User"> <constructor-arg name="name" index="0" value="张三"></constructor-arg> <constructor-arg name="age" type="java.lang.Integer" value="22"></constructor-arg> <constructor-arg name="car" ref="car"></constructor-arg> </bean>set方法注入
property标签<bean name="user" class="cn.it.domain.User"> <!--一个property属性代表调用一次set方法--> <property name="name" value="James"></property> <property name="age" value="22"></property> <property name="car" ref="car"></property> </bean>
p名称空间
导入p名称空间xmlns:p="http://www.springframework.org/schema/p"
p:属性名= | p:属性名-ref=<bean name="user" class="cn.it.domain.User" p:name="curry" p:age="27" p:car-ref="car"></bean>SPEL表达式
SPEL:spring expression language spring 表达式语言,只能引用属性,不能引用对象.
在配置文件中使用#{spel}来引用其他Bean的属性值.<bean name="user" class="cn.it.domain.User" > <property name="age" value="user.age"></property> <property name="name" value="curry"></property> </bean>复杂类型注入
Array
1.只有一个值可以直接使用value|ref<property name="arr" value="product"></property>
2.如果多个值,元素<property name="arr"> <array> <value>pro</value> <ref bean="product" /> </array> </property>List
1.只有一个值可以直接使用value|ref<property name="list" value="car"></property>
2.如果多个值,元素
|-
|-<property name="list"> <list> <value>c</value> <ref bean="car"></bean> </list> </property>Map
|-填写键值对<property name="map"> <map> <entry key="" value=""></entry> <entry key="" value-ref=""><entry> <entry key-ref="" value-ref=""></entry> <map> </property>Properties
|-填写键值对<property name="prop"> <props> <prop key="jdbc.driver" value="com.mysql.jdbc.Driver"></prop> <prop key="jdbc.username" value="root"></prop> </props> </property>spring配置详解(注解)
准备工作
导包
|4+2
|spring-aop导入约束
spring-context-4.2.xsd开启注解配置
<!--指定扫描哪个包中的注解,指定的包以及子孙包都会扫描--> <context:component-scan base-package="cn.it"></context:component-scan>注解
注册对象
@component(“user”)
@controller(“user”)
@service(“user”)
@Repository(“user”)指定对象域作用域
@Scope(“singleton”)指定对象生命周期
@PostConstruct 初始化
@PreDestory 销毁值注入
@value
1.成员变量,直接为成员变量赋值
2.set方法,调用set方法赋值注入引用类型
1.@AutoWired根据类型自动装配
2.@AutoWired和@Qulifier配合,@Qualifier(“car”)
3.@Resource直接指定注入的对象名,@Resource(name=”car”)spring整合JDBC(JDBCTemplate)
spring框架提供一个可以完成jdbc操作的对象,该对象可以放置到spring容器中.
spring准备的操作数据库的类,与QueryRunner类的设计与使用几乎完全相同.导包
4+2
spring-jdbc、spring-tx
数据库驱动、c3p0连接池JDBCTemplate工具类
jt.update(String sql,Object…params)增删改public void save(User u){ String sql ="insert into t_user value(null,?) "; getJdbcTemplate().update(sql,user.getName); }
jt.queryForObject(sql,class,params),查询单个值,并指定返回值类型//查询总数 public Integer getTotalCount(){ String sql = "select Count(*) from t_user "; getJdbcTemplate().queryForObject(sql,Integer.class); }
jt.queryForObject(sql,rowMapper,params),执行查询,并手动封装结果到对象中.返回单个对象//根据id查对象 public User getById(Integer id){ String sql = "select * from t_user where id=?"; return getJdbcTemplate().QueryForObject(sql,new RowMapper<User>(){ public User mapRow(ResultSet rs,int index ) throws SQLException{ User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); return user; } },id); }
jt.query(sql,rowMapper,params),执行查询,手动封装结果,返回List//查询所有的User public List<User> getAll(){ String sql = "select * from t_user"; return getJdbcTemplate().QueryForObject(sql,new RowMapper<User>(){ public User mapRow(ResultSet rs,int index) throws SQLException{ User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); return user; } }); }JdBCDaoSupport
继承JdbcDaoSupport,减少一层依赖关系.源码中已经帮我们接收JdbcTemplate
好处:可以减少一级依赖关系.直接将连接池对象注入给Dao即可。使用DB.properties管理连接信息
在src下创建properties文件,文件配置数据库信息
spring配置文件中读取:
在配置中引用,${key}spring中aop开发
aop&代理
spring中封装的代理技术
动态代理
局限性:生成代理类时必须基于接口.生成的代理对象实际上就是接口的实现类.
spring中的aop是希望能够对所有对象生成代理的.基于该动态代理原则会导致
项目中很多类无法生成代理.
CGLib代理
spring为了能够对项目中所有类生成代理.所以引入了cglib这个第三方代理技术.该代理技术的特点是.对目标对象生成代理时,代理对象是被代理对象的子类.
hibernate中应用了CGLib代理,懒加载技术中返回的就是cglib代理对象.aop中的名称解释
aop联盟制定规范
连接点 join point:目标对象中所有可以增强的方法.
切点 point cut:已经或即将增加的方法.
通知 advice:我们需要对目标方法增强的代码.
目标对象 target:我们需要增强的对象
代理对象 proxy:将通知应用到目标对象生成的对象
织入 weaving:将通知织入到目标对象的过程.
切面 aspect|advistor:切点+通知springAOP开发步骤(注解)
导包
目标对象
通知对象
配置注解
注解详解xml中配置
注册目标对象<bean name="userService" class="cn.it.service.impl.UserService"></bean>
注册通知对象<bean name="myAdvice" class="cn.it.test.MyAdvice"></bean>
开启使用注解配置aop<aop:aspectj-autoproxy></aop:aspectj-autoproxy>代码中配置注解
@Aspect 表示该类是通知类@Aspect pbublic class MyAdvice{}
@Before(“execution(表达式)”) 前置通知
@Around(“execution(表达式)”) 环绕通知
@AfterRunner(“execution(表达式)”) 后置通知
@After(“execution(表达式)”) 后置通知,不管是否抛异常,都执行
@AfterThrowing(“execution(表达式)”) 异常拦截通知//注册切点 @Pointcut(execution(* cn.it.service.impl.*ServiceImpl.*(..))) public void myPc(){} //前置通知 @Before("MyAdvice.myPc()") public void before(){}springAOP开发步骤(xml)
导包
目标对象
通知对象
配置xml
xml配置详解<aop:config>
<!--1.注册目标对象-->
<bean name="userService" class="cn.it.service.impl.UserServiceImpl"></bean>
<!--2.注册通知对象-->
<bean name="myAdvice" class="cn.it.test.MyAdvice"></bean><!--3.配置切面-->
<!--注册切点-->
<aop:pointcut id="myPc" exception="execution(* cn.it.service.*serviceImpl.*(..))" />
<!--配置切面,method对应要增强的方法,pointcut-ref对应切点-->
<aop:aspect ref="myAdvice">
<aop:before method="before" pointcut-ref="myPc"/>
<aop:around method="around" pointcut-ref="myPc"/>
<aop:after method="after" pointcut-ref="myPc"/>
<aop:after-returning method="afterReturning" pointcut-ref="myPc"/>
<aop:after-throwing method="afterThrowing" poingcut-ref="myPc"/>
</aop:aspect>
</aop:config>Spring中的aop事务管理
事务属性
传播行为(PROPAGATION)默认选择REQUIRED
是否只读(only-read)true|false
隔离级别springAOP事务管理(XML) ###
导包
创建Dao层对象
创建Service层对象
创建Spring配置文件
spring文件配置详解<!--指定读取properties文件--> <context:property-placeholder location="classpath:db.properties" /> <!--配置连接池--> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}" /> <property name="jdbcUrl" value="${jdbc.jdbcUrl}" /> <property name="user" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> </bean> <!--配置dao--> <bean name="userDao" class="cn.it.dao.impl.UserDao" > <property name="dataSource" ref="dataSource"></property> </bean> <!--配置service--> <bean name="userService" class="cn.it.service.impl.UserService"> <property name="userDao" ref="userDao"></property> </bean>
配置事务
引入tx约束<!--配置核心事务管理器--> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--事务通知&事务属性--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--配置事务属性--> <tx:attributes> <tx: method="before" propagation="REQUIRED" read-only="false" isolaction="REPEATABLE_READ" /> <tx: method="around" propagation="REQUIRED" read-only="false" isolaction="REPEATABLE_READ" /> ec7e </tx:attributes> </tx:advice> <!--配置切面完成织入--> <aop:config> <!--配置切点--> <aop:pointcut exception="execution(* cn.it.test.*serviceImpl.*(..))" id="txPc"/> <!--配置切面--> <aop:aspect advice-ref="txAdvice" pointcut-ref="txPc" /> </aop:config>springAOP事务管理(注解) ###
导包
创建Dao层对象
创建Service层对象
创建Spring配置文件
spring文件配置详解<!--指定读取properties文件--> <context:property-placeholder location="classpath:db.properties" /> <!--配置连接池--> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}" /> <property name="jdbcUrl" value="${jdbc.jdbcUrl}" /> <property name="user" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> </bean> <!--配置dao--> <bean name="userDao" class="cn.it.dao.impl.UserDao" > <property name="dataSource" ref="dataSource"></property> </bean> <!--配置service--> <bean name="userService" class="cn.it.service.impl.UserService"> <property name="userDao" ref="userDao"></property> </bean>
配置注解
//使用注解管理事务
@Transactional(paragation=Paragation.REQUIRED,readOnly=false,isolaction=Isolaction.REPEATABLE_READ)
public class UserServiceImpl implements UserService{@Transactional(paragation=Paragation.REQUIRED,readOnly=true,isolaction=Isolaction.REPEATABLE_READ) public void transaction()
}spring整合hibernate、struts2
导包
hibernate lib下required
struts2 apps下struts2-blank(删除与hibernate相同的包)
spring
core、context、bean、exception、log4j、logging
spring-jdbc、spring-tx、spring-orm
数据库驱动、c3p0连接池
spring-aop、spring-aspect
aspectj织入、aop联盟
spring-web
spring-test、junit4
web jstl整合spring到web项目
配置监听器,让spring随项目的启动而创建容器
<listener> <listener>org.springframework.web.context.ContextLoaderListener</listener> </listener> <!--指定容器配置文件位置--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>准备spring配置文件
在src目录下创建applicationContext.xml,导入4个约束,bean、context、tx、aop<!--配置dao--> <bean name="userDao" class="cn.it.dao.impl.UserDaoImpl"> </bean> <!--配置service--> <bean name="userService" class="cn.it.service.impl.UserServiceImpl" > <property name="ud" ref="userDao"></property> </bean> <!--配置Action--> <bean name="userAction" class="cn.it.web.action.UserAction"> <property name="us" ref="userService"></property> </bean>整合struts2到web项目
创建Action
创建Action的三种方式
pojo(普通java对象,不需要实现任何接口|任何类)
实现Action
继承ActionSupport
获取表单数据的三种方式
属性驱动
对象驱动
模型驱动创建配置文件
<struts> <package name="crm" namespace="/" extends="struts-default"> <action name="userAction_*" class="cn.it.web.action.UserAction" method="{1}"> <result="success">/login.jsp</result> </action> </package> </struts>配置入口过滤器
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>spring整合struts2
配置整合spring常量
<context-param> <param-name>struts.objectFactory</param-name> <param-value>spring</param-value> </context-param>方案1:Action对象仍然由struts2创建,spring负责组装依赖.
<!--配置常量,指定由spring完成属性注入--> <context-param> <param-name>struts.objectFactory.spring.autoWire</param-name> <param-value>name</param-value> </context-param> 在action中准备依赖属性 <!--在spring中配置依赖属性--> <bean name="us" class="cn.it.service.impl.UserServiceImpl" ></bean>方案2:Action对象创建与依赖注入全都由spring完成
将Action配置到spring容器中 <bean name="userAction" class="cn.it.web.action.UserAction"> <property name="us" ref="userService"></property> </bean> 在Action配置中的class属性,填写对象的BeanName <action name="userAction_*" class="userAction" method="{1}"> <result name="success" >/login.jsp</result> </action>搭建Hibernate框架
准备实体与映射文件
准备实体
映射文件 User.hbm.xml<hibernate-mapping package="cn.it.domain"> <class name="User" table="tb_user"> <!--配置主键--> <id name="u_id" column="u_id"> <generator class="native"></generator> </id> <!--配置普通属性--> <property name="u_name" column="u_name"></property> <property name="u_age" column="u_age"></property> <property name="u_gender" column="u_gender"></property> </class> </hibernate-mapping>准备主配置文件
在src目录下创建hibernate.cfg.xml<hibernate-configuration> <session-factory> <!--配置5个必选--> <!--配置3个可选--> <!--配置映射文件--> <mapping resource="cn/it/domain/User.hbm.xml"></mapping> </session-factory> </hibernate-configuration>整合spring与hibernate
整合方式1:使用原生Hibernate配置文件
<!--配置sessionFactory--> <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> </bean>整合方式2:将hibernate中的配置转移到spring中
<!--将hibernate中的配置转移到spring中--> <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <!--指定可选|必选属性--> <property name="hibernateProperties"> <props> <!--必选--> <prop key=""></prop> <!--可选--> <prop key=""></prop> </props> </property> <!--引入映射文件--> <property name="mappingDirectoryLocations" value="classpath:cn/it/domain"></property> </bean>将c3p0连接池配置到spring
1.准备DB.properties
2.读取db.properties
<context:property-placeholder loaction="classpath:db.properties" />3.配置连接池对象,并注入连接配置
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"><property> <property name="driverClass" value="${jdbc.driverClass}"><property> <property name="user" value="${jdbc.user}"><property> <property name="password" value="${jdbc.password}"><property> </bean>4.将连接池对象注入到sessionFactory中
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <!--将连接池对象注入到sessionFactory中--> <property name="dataSource" ref="dataSource"></property> <!--指定可选|必选属性--> <property name="hibernateProperties"> <props> <!--必选,其中4个没用了,只保留数据库方言--> <prop key=""></prop> <!--可选--> <prop key=""></prop> </props> </property> <!--引入映射文件--> <property name="mappingDirectoryLocations" value="classpath:cn/it/domain"></property> </bean>将Dao&Hibernate模板配置到spring
书写Dao类
配置hibernate模板到spring
<bean name="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>配置dao到spring
<bean name="userDao" class="cn.it.dao.impl.UserDaoImpl"> <property name="ht" ref="hibernateTemplate"></property> </bean>整合AOP事务
1.完成Service
<!--配置service--> <bean name="userService" class="cn.it.service.impl.UserServiceImpl"> <property name="ud" ref="userDao"></property> </bean>2.配置核心事务管理器
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>XML|注解事务配置
xml配置<!--配置事务通知--> <tx:advice name="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" progation="REQUIRED" read-only="false" isolaction="REPEATABLE_READ" /> </tx:attributes> </tx:advice> <!--配置切面--> <aop:config> <aop:pointcut expression="execution(* cn.it.service.*serviceImpl.*(..))" id="myPc" /> <aop:advisor advice-ref="adAdvice" pointcut-ref="myPc" /> </aop:config>
注解<!--开启注解管理事务"开关"--> <tx:annotation-driven transaction-manager="transactionManager" /> service中使用注解 @Transaction(progation=Progation.REQUIRED,readOnly=true,isolaction=Isolaction.REPEATABLE_READ) publlic class UserServiceImpl implments UserService{ }解决no-session问题
配置扩大session作用范围的过滤器<filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter<filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
相关文章推荐
- Spring框架的AOP/IOC/容器核心原理实例详解
- Spring框架IOC和AOP的实现原理与详解
- 模拟SSH之--spring框架的IOC和AOP机制模拟
- SSH中各个框架的作用以及Spring AOP,IOC,DI详解
- 关于spring框架中的IOC/DI和AOP,以及声明式事务管理的理解
- spring框架的ioc和aop通俗解释
- Spring框架,个人笔记--IOC,DI,AOP
- spring框架的IOC和AOP机制模拟
- 详解Spring框架---IOC装配Bean
- Spring框架的 IoC和AOP
- Spring框架中IOC和aop
- Spring框架的两个重要概念IOC 和 AOP
- (精简)Spring框架的IoC(替代工厂类实现方法)和AOP(定义规则,约定大于配置)
- SSH中各个框架的作用以及Spring AOP,IOC,DI详解
- Spring IOC AOP详解(一)
- Spring AOP详解 (转) 以及IOC(个人理解)
- Spring框架的IoC和AOP
- 深入浅出学习Spring框架(三):AOP 详解
- Spring框架IOC与AOP简单应用浅解-适合初入SSH框架学习
- 详解Spring框架AOP(面向切面编程)