spring相关

spring 控制反转

控制权的转移,由spring负责对象的创建和维护。

注入方式

自动装配:@Autowired

此处暂略

setter方法注入

需要创建bean的成员对象的setter方法

    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--配置当前类中相应的属性-->  
        <property name="springDao" ref="springDao"></property>  
    </bean>  
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  

构造注入

注入带参数构造函数的bean

    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--创建构造器注入,如果主类有带参的构造方法则需添加此配置-->  
        <constructor-arg ref="springDao"></constructor-arg>  
        <constructor-arg ref="user"></constructor-arg>  
    </bean>  
        <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
         <bean name="user" class="com.bless.springdemo.vo.User"></bean>  

静态工厂的方法注入

通过调用静态工厂的方法来获取自己需要的对象

    <bean name="springAction" class="com.bless.springdemo.action.SpringAction" >  
        <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->  
        <property name="staticFactoryDao" ref="staticFactoryDao"></property>  
                </property>  
    </bean>  
    <!--此处获取对象的方式是从工厂类中获取静态方法-->  
    <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>  

实例工厂的方法注入

获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法

    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->  
        <property name="factoryDao" ref="factoryDao"></property>  
    </bean>  
      
    <!--此处获取对象的方式是从工厂类中获取实例方法-->  
    <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>  
    <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean> 

bean的作用域

分别为singleton、prototype、request、session、global session
bean的作用域由scope属性设置,默认singleton

单例:singleton

每个容器只存在一份

prototype

每次向ioc容器获取bean时创建新的实例

request

每次http请求创建一个实例且仅在当前request内有效

session

该属性仅用于HTTP Session,同一个Session共享一个Bean实例。不同Session使用不同的实例。

global session

该属性仅用于HTTP Session,同session作用域不同的是,所有的Session共享一个Bean实例

bean的生命周期

定义、初始化、使用、销毁

定义

通过构造器或工厂方法创建Bean实例,为Bean的属性设置值或对其它Bean的引用

初始化

调用bean初始化方法

使用

用户从spring ioc容器中获取实例并使用

销毁

调用bean销毁方法

    <!--方式1:xml配置init-method属性和destory-method属性,执行bean对于的init和destory方法-->
    <bean id="person" class="com.test.Person" init-method="init" destroy-method="destory">
        <property name="name" value="xujian"></property>
        <property name="age" value="23"></property>
        <property name="sex" value="男"></property>
    </bean>
public class TestInitializingBean implements InitializingBean,DisposableBean{
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("run InitializingBean");        
    }

    @Override
    public void destory() throws Exception {
        System.out.println("run destory");        
    }
}

注解

类的自动检测

<!--检测类并注册bean,context:component-scan包含了context:annotation-config-->
<context:component-scan base-package="com.xyg.pojo"></context:component-scan>

作用域:@Scope

@Component
@Scope("prototype")
public class AnnotationTest {

    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void getName(){
        System.out.println("调用方法");
    }


}

自动装配:@AutoWired

//setter注入
@Component
public class AutoService {
	
	AutoDao autoDao;

	@Autowired
	public void setAutoDao(AutoDao autoDao) {
		this.autoDao = autoDao;
	}
	
	public void say(String message){
		autoDao.say(message);
	}
}
//成员注入
@Component
public class AutoService {
	@Autowired
	AutoDao autoDao;
	
	public void say(String message){
		autoDao.say(message);
	}
}

@Qualifier

按类型装配可能有多个bean实例情况,可使用Qualifier缩小范围

@Service("service")
public class EmployeeServiceImpl implements EmployeeService {
    public EmployeeDto getEmployeeById(Long id) {
        return new EmployeeDto();
    }
}

@Service("service1")
public class EmployeeServiceImpl1 implements EmployeeService {
    public EmployeeDto getEmployeeById(Long id) {
        return new EmployeeDto();
    }
}

//成员上的Qualifier
public class EmployeeInfoControl {
    
    @Autowired
    @Qualifier("service")
    EmployeeService employeeService;
}

@Bean

@Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名

定义一个bean

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }

}

等价于

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

自定义bean的命名

默认情况下bean的名称和方法名称相同,你也可以使用name属性来指定

@Configuration
public class AppConfig {

    @Bean(name = "myFoo")
    public Foo foo() {
        return new Foo();
    }

}

接受生命周期的回调

public class Foo {
    public void init() {
        // 初始化逻辑
    }
}

public class Bar {
    public void cleanup() {
        // 销毁逻辑
    }
}

@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public Foo foo() {
        return new Foo();
    }

    @Bean(destroyMethod = "cleanup")
    public Bar bar() {
        return new Bar();
    }

}

AOP面向切面编程

https://www.imooc.com/video/15678

概念

是一种编程范式(其他变成范式:面向过程、面向函数)

目的

DRY:解决代码重复问题
SOC:关注点分离

Spring AOP注解

@Aspect

表示该类是一个切面的配置类

@pointcut

表示那些类那些方法上来植入代码,由切面表达式组成

@Pointcut("@annotation(AdminOnly)")
public void adminOnly(){
}

Advice

包括@Before,@After等,表示在方法的之前/之后进行代码的植入

切面表达式

格式:@Pointcut("切入点表达式"),方法体通常是空的。

匹配包/类型

@Pointcut("within(com.xyg.Service.UserService)")
public void matchType(){}

匹配对象

  @Pointcut("this(com.xyg.DemoDao)")
   public void thisDemo(){}//匹配指定类型的方法
  
  @Pointcut("target(com.xyg.IDao)")
   public void targetDemo(){}//匹配接口

   @Pointcut("bean(*Service)")
   public void BeanDemo(){}//匹配以Service结尾的Bean

execution表达式

1、execution(): 表达式主体。
2、第一个号:表示返回类型,号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
4、第二个号:表示类名,号表示所有的类。
5、(..):最后这个星号表示方法名,号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

例子

@Component
public class AdviceDao {
	public void say(){
		System.out.println("原始方法");
	}
}
 
@Aspect
@Component
public class AdviceTest {
	
	//前置切点,值可以切点引用,也可以直接写切点表达式
	@Before("execution(* com.how2java.dao.AdviceDao.*(..))")
	public void before(){
		System.out.println("前置通知。。。。。");
	}
	
	@Around("execution(* com.how2java.dao.AdviceDao.*(..))")
	public void around(ProceedingJoinPoint point) throws Throwable{
		System.out.println("环绕通知前。。。。");
		point.proceed();
		System.out.println("环绕通知后。。。。");
	}
	
	@AfterReturning("execution(* com.how2java.dao.AdviceDao.*(..))")
	public void after(){
		System.out.println("后置通知。。。。。");
	}
}

对应的xml表示

    <!-- 开启对aop注解的支持 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <!--声明aop配置-->
    <aop:config>
    	<aop:pointcut expression="execution(* com.how2java.dao.AdviceDao.*(..))" id="advicePoint"/>
    	
        <!--定义通知类型-->
    	<aop:aspect id="adviceAspect" ref="advice">
    		<aop:after-returning method="after" pointcut-ref="advicePoint"/>
    		<aop:around method="around" pointcut-ref="advicePoint"/>
    		<aop:before method="before" pointcut-ref="advicePoint"/>
    	</aop:aspect>
    </aop:config>	

Spring对代理模式的选择

如果目标对象实现了接口用JDK动态代理,没有实现接口用cglib进行动态代理,如果实现了接口且强制cglib代理,则使用cglib代理。


springMVC原理

客户端发送请求-> 前端控制器 DispatcherServlet 接受客户端请求 -> 找到处理器映射 HandlerMapping 解析请求对应的 Handler-> HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑 -> 处理器返回一个模型视图 ModelAndView -> 视图解析器进行解析 -> 返回一个视图对象->前端控制器 DispatcherServlet 渲染数据(Moder)->将得到视图对象返回给用户

版本2: SpringMVC是Spring中的模块,它实现了mvc设计模式的web框架,首先用户发出请求,请求到达SpringMVC的前端控制器(DispatcherServlet),前端控制器根据用户的url请求处理器映射器查找匹配该url的handler,并返回一个执行链,前端控制器再请求处理器适配器调用相应的handler进行处理并返回给前端控制器一个modelAndView,前端控制器再请求视图解析器对返回的逻辑视图进行解析,最后前端控制器将返回的视图进行渲染并把数据装入到request域,返回给用户。
DispatcherServlet作为springMVC的前端控制器,负责接收用户的请求并根据用户的请求返回相应的视图给用户。


spring事务

参考

事务隔离级别

隔离级别 含义
DEFAULT 使用后端数据库默认的隔离级别(spring中的默认选择项)
READ_UNCOMMITED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

Mysql 默认隔离级别 REPEATABLE_READ,Oracle 默认隔离级别 READ_COMMITTED

事务的传播行为

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为:

传播行为 含义
PROPAGATION_REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
PROPAGATION_NEVER 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
PROPAGATION_NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务

主要分3大类

1)PROPAGATION_REQUIRED(默认值)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY
支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务 。
事务默认传播行为 REQUIRED。最常用的。
2)PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER
不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务。
常用的事务传播行为:PROPAGATION_REQUIRES_NEW
3) PROPAGATION_NESTED
嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点

【面试题】REQUIRED、REQUIRES_NEW、NESTED 区分
REQUIRED:只有一个事务(默认,推荐)
REQUIRES_NEW:存在两个事务,如果事务存在,挂起事务,重新又开启了一个新的事务
NESTED:嵌套事务,事务可以设置保存点,回滚到保存点 ,选择提交或者回滚

posted @ 2019-03-05 22:56  熊云港  阅读(261)  评论(0编辑  收藏  举报