Spring基础

容器--------Spring包含并管理JavaBean的配置和生命周期
框架--------Spring可以将简单的组件配置、组合成复杂的应用
轻量--------Spring完整的框架可以在一个只有1M多的JAR文件中发布
IOC(控制反转)Spring通过控制反转促进了松耦合,对象依赖关系通过被动的方式传递进来
AOP(面向切面)Spring提供了面向切面的变成的丰富支持,允许通过分离应用的业务逻辑与其他系统服务进行开发
应用对象只实现它们的业务逻辑就可以了,日志记录、事务处理、错误处理等功能写在另外一个地方,由Spring组合在一起


主要完成了本来应该是new完成的实例化,交给了Spring利用setter注入
第一步:配置文件web.xml中配置
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>


第二步:新建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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!--发动机类  -->
<bean id="e" class="spring.AutoE"></bean> <bean>代表放入Spring容器的JavaBean对象
<!--轮胎类 --> 所有的类都由Spring管理
<bean id="t" class="spring.Tired" p:r="200" /> id为对象名称、class为完全限定类名(包+类)
<bean id="autocar" class="spring.Car"> p:注入的对象名称="对象值";class里用setter获取
<description>通过setter方法注入对象</description> 注释标签description
<property name="e" ref="e1"></property> ref="上面的对象id" name="注入对象时接受参数"
<property name="t" ref="t1"></property> 需要用setter获取,类型为对应的接口
<property name="r" value="opo"></property> 用setter获取r对象值为opo
ref是指上面bean里对象 (引用类型), value(传值类型),只存在一种
</bean>
<bean id="ca" class="spring.Ca"> 
<description>通过构造方法注入对象</description>
<constructor-arg ref="e"></constructor-arg>
<constructor-arg ref="t"></constructor-arg>
</bean>
<bean id="cars" class="spring.Car"/>
</beans>


第三步:创建测试类,运行效果
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
//ApplicationContext是接口,也可以是接口类型,也可以是ClassPathXmlApplicationContext类型,得到Spring容器
Car autocar=(Car) context.getBean("car");
//从Spring容器中取出id为car的JavaBean对象,返回的是Object对象,所以可以强制转换为对应的对象
//分开来写是这样的Object autocar=context.getBean("car");Car a = (Car) autocar;a.run();
autocar.run();
//调用car里的run方法




使用P命名空间:
<bean id="autocar" class="spring.Car">
<property name="e" ref="e1"></property>
<property name="t" ref="t1"></property>
</bean>
和上面是相同的意思,name是这setter里建立的东西,ref是bean的id,在下方中":"和"-"之间的是name,ref是bean的id
    <bean id="auto" class="spring.Car" p:e-ref="e1" p:t-ref="t1" />
上述的p:r="200",同理,这里少了-ref,故,后者只是常规参数(基本数据类型,字符串)


autowire自动注入(如果想让所有的都自动注入,在配置文件第一句[一堆堆网站后面]加上default-autowire="byName")
p标签虽然方便,但面对太多的属性时候,还是扛不住,这时候,需要利用bean中autowire的属性,该属性有:
no 默认的值'defaule',Spring不进行自动装配,必须显式指定依赖对象
byName 根据属性名自动装配,自动找到属性名相同的id,找到自动注入,反之什么也不做
byType 根据属性的类型进行装配,找到唯一一个,则自动注入,如果找到多个,则抛出异常,反之什么也不做
constructor 与byType类似,不过它针对构造方法,构造方法注入,通过中的全参构造方法.


Spring中有三种注入方式:接口注入、setter注入、构造器注入
构造器注入:
public class Ca {
private Engine e;
private Tire t;
public Ca() {
// TODO Auto-generated constructor stub
super();
}
public Ca(Engine e,Tire t) {
// TODO Auto-generated constructor stub
this();
this.e=e;
this.t=t;
}
}
<bean id="ca" class="spring.Ca"> 
<description>通过构造方法注入对象</description> 没有的时候是使用时不分先后顺序
<constructor-arg ref="e" index="0"></constructor-arg> 通过index可以指定该参数位置构造方法第一位为0
<constructor-arg ref="t" type="spring.Engine"></constructor-arg>通过type可以指定类型,包+接口名称
</bean>




Bean的作用域(scope)
scope="singleton" 默认值,仅仅建立一次唯一的实例,下次请求直接返回被缓存的实例
prototype 每次请求一次,都会重新产生一个新的实例,相当于new,交给客户端,清除对象,释放全部资源
request 在不同的用户请求,返回不同的实例
session 同上,区别作用域不同
global session 全局的HttpSession,容器会返回该bean的同一个实例
后三者需要在web.xml中配置(request、session、global session)
<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
当然,用户还可以利用Spring的作用域接口org.springframework.beans.factory.config.Scope来定义,不能覆盖singleton,prototype




AOP概述
try {
System.out.println("调用前置增强"); //Before advice 连接点之前执行的增强 org.springframework.aop.MethodBeforeAdvice
System.out.println("环绕前置处理"); //Around advice 包围一个连接点的增强 org.aopalliance.intercept.MethodInterceptor
System.out.println("调用目标对象方法");
System.out.println("环绕后置处理");
System.out.println("调用后置增强"); //After returning advice 连接点正常后执行的增强 o.s.a.AfterReturningAdvice
} catch (InterruptedException e) {
// TODO: handle exception
System.out.println("调用异常增强"); //After throwing advice 抛出异常退出时执行的增强 o.s.a.ThrowsAdvice
}finally{
System.out.println("调用最终增强"); //After(finally) advice 连接点退出的时候执行的增强 o.s.a.AfterAdvice
} //早期用于接口实现的,也就是后面的接口




第一步:制作切点方法(蔬菜和水果类)


//放在类的上面,表示这个类是Spring容器中的一个切点
@Aspect
public class LoggerAdvice {
//后置增强 value 用于定义切点 后面告诉Spring那些地方需要进行后置增强的织入
//pointcut和value作用相同,如果指定,将会覆盖value
//returning:目标方法的返回值绑定给他
//第二个参数,argNames:当用户想从切点方法得到参数时
@AfterReturning(pointcut="execution(* org..*.*(..))",returning="ret")
public void afterReturning(JoinPoint join,Object ret){
String method=join.getSignature().getName();
Object[] args=join.getArgs();
if("login".equals(method)){
if(ret!=null){
User rets =(User) ret;
System.out.println(rets.getName()+"name");
System.out.println(rets.getPass()+"pass");
System.out.println(new Timestamp(System.currentTimeMillis())+""+args[0]+"登陆成功");
System.out.println("后置增强");
}else {
System.out.println(new Timestamp(System.currentTimeMillis())+""+args[0]+"登陆失败");
}
}
}
//前置增强 value用于定义切点 后面告诉Spring那些地方需要进行前置增强的织入
//括号内第一个*表示返回值
//..*表示包,和所有的子包
//.*表示所有的类
//..表示所有的参数
//最终表示:方法返回值为任意值(* ) org这个包和所有的子包(..*)中所有的类(.*),所有的方法((.),方法的参数为任意类型(.))

//*只能匹配一个元素,匹配任何字符
//..匹配任意字符,可以匹配多个元素,表示类时,必须和*一起使用,表示参数时,可以单独使用
//+表示按类型匹配指定类的所有类,仅能跟在类名后面
@Before(value="execution(* org..*.*(..))" )
//第二个参数,argNames:当用户想从切点方法得到参数时
public void methodBefore(JoinPoint join){
//获取类型join.getSignature().getDeclaringTypeName();
//获取调用方法的方法名String method=join.getSignature().getName()||.toString()全名;
//获取参数值getArgs()例:Object[] args=join.getArgs(); args[0]、args[1]
String method=join.getSignature().getName();
Object[] args=join.getArgs();
if("login".equals(method)){
System.out.println(new Timestamp(System.currentTimeMillis())+""+args[0]+"开始登陆");
System.out.println("前置增强");
}
}
//Around 环绕增强 value、argNames
//AfterThrowing 抛出增强 value、pointcut、argNames、throwing:将抛出异常绑定到增强方法当中
//After 最终增强 value、argNames
}


第二步:配置文件
<?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"
>
<!-- 日志记录类 -->
<bean id="lggerAdvice" class="spring.LoggerAdvice"></bean>
<!--模拟数据库环境 -->
<bean id="userDao" class="org.UserDaoImpl"></bean>
<!-- 模拟业务环境 -->
<bean id="userBiz" class="org.UserBizImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- aop自动代理 -->
<aop:aspectj-autoproxy />
</beans>




正常的业务
@Before(value="execution(* org..*.*(..))" )
public void Before(JoinPoint j){
String method=j.getSignature().getName();
System.out.println(method);
System.out.println("前置增强");
}
@AfterReturning(pointcut="execution(* org..*.*(..))",returning="ret")
public void afterReturning(){
System.out.println("我是后置增强");
}
@AfterThrowing(value="execution(* org..*.*(..))")
public void AfterThrowing() {
// TODO Auto-generated method stub
System.out.println("我是异常增强");
}

@After(value="execution(* org..*.*(..))")
public void After() {
// TODO Auto-generated method stub
System.out.println("我是最终增强");
}
@Around(value="execution(* a..*.*(..))")
public Object around(ProceedingJoinPoint join) throws Throwable{
System.out.println("环绕开始");
//运行方法
Object result = join.proceed();
//运行方法后
System.out.println("环绕结束");
return result;
}




Ioc注解:
@Component 通用注解,表示该类为Spring管理的Bean 例:@Component("Gsp")=@Component(value="Gsp") id为gsp的bean
@Repository Dao类注解,使用方法和Component相同
@Service 业务逻辑类注解,使用方法和Component相同
@Controller 控制器类,使用方法和Component相同
@Autowired 注解实现自动注入,默认按照byType自动注入(由Spring提供)
@Resource 注解实现自动注入,默认按照byName自动注入
@Qualifier 按照指定的名称进行注入
配置文件
<?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"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
<!-- 自动织入增强 -->
<aop:aspectj-autoproxy />
<!-- 自动扫描注解 -->
<context:component-scan base-package="org." />
</beans>
@Scope 注解Bean的作用域










详细解析Spring事务的配置和OpenSessionInview的作用


1.事务的特性
  原子性:事务中的操作是不可分割的一部分
  一致性:要么同时成功,要么同时失败(事务执行前后数据保持一致)
  隔离性:并发互不干扰  
  持久性:事务一旦被提交,它就是一条持久性的数据
  
 2.Spring事务管理高层抽象3个接口
    PlatformTransactionManager--平台事务管理器
      -Spring为不同的持久化框架提供了不同的平台事务管理器接口实现
    TransactionDefinition--事务定义信息(隔离,传播,超时,只读)
      1>事务的隔离级别
        default--适用后端数据库默认的隔离级别
        READ_UNCOMMITED - READ_COMMITTED - REPEATABLE_READ - SERIALIZABLE(脏,幻(虚),不可重复读)
      2>事务的传播行为:解决业务层方法之间相互调用的问题
        PROPAGATION_REQUIRED - 支持当前事务,如果不存在就新建一个
        PROPAGATION_REQUIRES_NEW - 如果有事务存在,挂起当前事务,创建一个新的事物
        PROPAGATION_NESTED - 如果当前事务存在,则嵌套执行
    TransactionStatus--事务具体运行状态
      1>------------------------------------------------------
    流程 --
        根据事务定义的信息有平台事务管理器进行事务管理,进行管理产生相应的状态
 
3.Spring事务管理
  - 编程式的事务管理 -- 通过TransactionTemplate(事务模板)
  - 使用xml配置声明式事务
    --基于transactionProxyFactoryBean的事务管理
      ---配置事务管理器
      ---配置业务层代理
      ---配置目标对象
      ---注入事务管理器
      ---注入事务
      <!--
prop格式 PROPAGATION--事务的传播行为 ISOLATION--事务的隔离级别        READONLY--只读
-EXCEPTION--发生哪些行为事务回滚 +EXCEPTION--发生哪些错误事务不回滚
-->
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置业务层代理 -->
<bean id="accountServiceProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置目标对象 -->
<property name="target" ref="accountService"></property>
<!-- 注入事务管理器 -->
<property name="transactionManager" ref="transactionManager"></property>
<!-- 注入事务属性 -->
<property name="transactionAttribute">
<props>


<prop key="tran*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>


--基于AspectJ的事务声明(重点)
    ---配置事务的增强
      ----事务定义信息
        -----propagation:事务的传播行为
        -----isolation:事务的隔离级别
        -----read-only:只读
        -----rollback-for:发生哪些异常时回滚
        -----no-rollback-for:发生哪些异常时不回滚
        -----timeout:过期信息
     ---配置切面
      ----配置切入点
      ----配置切面
      <!-- 配置事务的通知(事务的增强) -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<!-- 事务定义信息 -->
<tx:attributes>
<tx:method name="tran*" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.spring.service.impl.*.*(..))"
id="pointcut" />
<!-- 配置切面 -->
<aop:advisor advice-ref="transactionAdvice" pointcut-ref="pointcut" />
</aop:config>
  
  --基于注解的方式进行事务的声明(重点)
    ---开启事务注解
        <tx:annotation-driven transaction-manager="transactionManager"/>
    ---在要进行实务操作的类名上进行注解
       @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)


hibernate中为了性能,一般采用代理加载,所以实现多表连接,外键表字段会因为session的关闭无法查询到,


这时候就需要在web.xml中配置opensessioninview -- 在页面中打开session


 <filter>
        <filter-name>OpenSessionInView</filter-name>
        <filter-class>
            org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
       </filter>
     <filter-mapping>
  <filter-name>OpenSessionInView</filter-name>
  <url-pattern>/*</url-pattern>
  </filter-mapping>


此时如果在页面上对数据进行写入操作(增加,删除,修改等),会出现read-only错误.这个错误可以配置事务解决
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值