spring

###hibernate一点补充,上一篇博客写不进去了
写在前面,补充一点,为什么需要ORM。当我们的数据库是面向关系的数据库(mysql,oracle),而我们的程序又是面向对象的,所以写代码的时候经常需要把类和表做转换。有了ORM就不需要了。。
####联合主键
关于马士兵hibernate比较细的知识点可以参考如下博客:自己写的太累了,把大量时间都浪费在记笔记和排版上面没有意义,别人有现成的为什么不拿来用呢? 站在巨人的肩膀上看世界。
http://blog.csdn.net/u012532092/article/details/79320934#t5

联合主键:对于数据库来讲,没什么变化。
但是对于编程来说,就得写一个主键类,然后在实体类中去引用它。

public class StudentPK implements Serializable {
                   private String id;
                   private String name;
 }
为什么主键类要实现序列化? 因为有的时候内存满了,就要用虚拟内存(就是把硬盘上的一部分空间拿来当做内存来使用), 这个时候就需要把对象从内存中移到硬盘里去了,也就需要序列化了。
而且主键类还一定要重写equals和hashcode方法,要保证能区分开不同的对象。为啥要重写hashcode,因为对象信息也有可能被装进哈希表里面去。

####顺带说说视频中提到的hash表,也比较重要
哈希表在底层很多时候是数组来实现的,两个对象的哈希码相同的话,他俩会被放在数组里面同一个位置。所以里面数组的位置上往往放的是一个链表,链表上所有的对象都是哈希码相同的对象。
查找对象:首先计算对象的哈希码,通过哈希码找到在数组里的位置,这个链表里有多个对象,然后再遍历每个对象和自己比较看是不是equals即可。

hibernate面试中可能会问到的:
1、创建session的两种方式的区别:
openSession(永远是创建一新的session) 、getCurrentsession(当前环境如果有session了就会拿当前环境的)。
即:(和openSession区别,一个是每次产生一新的,一个是从上下文找。上下文主要有两种,一个是JTA,一个是thread)
检验办法如下:
什么叫当前环境已经有了session??session.commit()了 ,一提交或者一回滚session就关闭了,如果再需要就会产生一新的session。原来的session对象就消失了。如果没有commit(),那永远用的就是同一个。
这里写图片描述
2、getCurrentsession的用途:
1>、(界定事务边界,如addUser和加日志必须要放在一个事务里).。其余区别见笔记。
2. 事务提交自动close
3. 上下文配置可设置在xml文件中,而且必须要设定上下文,否则找不到session。
关于上下文:thread和jta的区别:

  <property name="current_session_context_classs">thread/jta</property>

thread的意思是线程,如果要拿到session的话,就去当前线程里去找,看有没有session。有就直接拿,没有就创一新的。 就thread就行,其余的不用管。
4. 这里connection怎么去管理事务?之前JDBC讲过,就是conn.setAutoCommit(false);设为false,然后执行操作,一遇到异常就rollback,没异常就commit。。这种方式是依赖数据库的事务能力。
JTA:
但是有一种事务是一个connection管理不了的,那就是分布式事务。-- 也称为JTA事务。,
它由第三方的(中间件)事务管理器来commit,如果失败,就要求其中一个数据库rollback回滚。tomcat本身是不具备JTA能力的,它需要中间件的支持。
所以事务大概可以分为2种:一种是依赖于数据库本身的 ,简单的可以说成是connection事务,还有一种是JTA事务,是分布式的。
####session的一些操作
详细的还是去看现成的笔记,这里只记录认为重要的。
get、load的区别:

 Object load(Class var1, Serializable var2);  注意,这里integer类实现了序列化接口
Students s = (Students) session.load(Students.class,1);  
1、load一个不存在的记录的时候,如果不发SQL语句,那就不报错。 而get立马报错
2、load生成的是对象的一个代理,等到真正用到对象的内容时才发出sql语句。而get直接从数据库加载,不会延迟
稍微延伸下:
动态代理在hibernate,spring,mybatis里都用到了。
javassist是hibernate动态生成代理的类库,它可以直接的生成二进制码,它不会弄一个源码出来再去编译一下生成这样的一个类,
它会直接生成二进制码,所以hibernate的这种动态代理效率还是比较高的。
自己模拟的时候采用的是编译的方式,但是实际当中用的时候不会用那种方式,都是用一些类库直接生成二进制码。
update:

####对象的三种状态
详情还是请问笔记
缓存:每次从硬盘里读太慢了,就放到内存里,这样读起来效率高。缓存就是内存中的一块区域。
transient:内存中一个对象,没ID,缓存中没有那个key和value
persistent:session是内存中一个对象,里面有一个Map,key是1,value就是是t对象。这里就是一个缓存。
detached:session,close之后,缓存没了,但是t对象还是有的,只是t现在已经脱离了session 的管理了。这就是detached
这里写图片描述

####阶段总结
1、sessionfactory。它里面管理着一系列的连接池,它用来产生session,然后从池里面拿出一个connection出来,挂到session上面。 一般地,全局只需要一个sessionfactory就可以了,这也是为啥它是单例模式的原因。
2、上下文有两种,thread和JTA。区别:如果用thread,管事务的时候用的就是connection的事务,数据库连接的事务。如果是JTA,管事务的时候用的是application server帮你提供的事务管理器,这种事务管理往往用在分布式事务上面。当然不是分布式你要用也没错,但是没必要。

####关系映射(重要)
笔记中红色部分是重点,面试和工作用的都很多
数据库表与表之间的关系:只有外键这种。
这里的对象关系不是继承,而是数量上的关系。

###Sping – 讲太罗嗦,只看IOC AOP和springBoot就可以了
####概述
这里写图片描述
spring是现在java在开源界最火的框架
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
框架 --房屋架子
类库 – 水泥,钢筋等材料
框架
####IOC
这里写图片描述
这里写图片描述

####马士兵spring
#####依赖注入或者控制反转,转到容器那里去了。。
马士兵的spring可以看看他写的spring.doc文档。。
反射机制:可以通过反射的api接口去探索运行期间的一个class的内部结构,并且根据它的内部结构来决定方法怎样进行调用。
spring开始:
面向接口编程(或者叫面向抽象类编程,讲完这个进而引出IOC。面向接口编程的好处就是灵活。
service层处理一些业务逻辑:权限认证等,报文转换等。
dao层:只是和数据库打交道。

依赖注入怎么实现:
读出id,id里面只要有property,看property名字是什么,生成set方法,用反射调一下,然后把bean注进来就可以。自己模拟的spring容器代码如下:

BeanFactory.java
public interface BeanFactory {
	public Object getBean(String id);
}
bean.xml
<beans>
	<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" />
	<bean id="userService" class="com.bjsxt.service.UserService" >
		<property name="userDAO" bean="u"/>
	</bean>
	
</beans>

首先把所有的bean放到容器中去,再看bean里面如果有子元素property则全部拿出来。再拼成set方法名字和方法的参数,


注意:@Component和@Resource完全可以替代xml的这种配置。效果是一样的,下面会讲到。。。


ClassPathXmlApplicationContext.java
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

//类名这么记:放在classpath下xml的应用上下文。
public class ClassPathXmlApplicationContext implements BeanFactory {
	
	private Map<String , Object> beans = new HashMap<String, Object>();
	
	
	//IOC Inverse of Control DI Dependency Injection
	public ClassPathXmlApplicationContext() throws Exception {
		SAXBuilder sb=new SAXBuilder();
	    
	    Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //构造文档对象
	    Element root=doc.getRootElement(); //获取根元素HD
	    List list=root.getChildren("bean");//取名字为disk的所有元素
	    for(int i=0;i<list.size();i++){
	       Element element=(Element)list.get(i);
	       String id=element.getAttributeValue("id");
	       String clazz=element.getAttributeValue("class");
	       Object o = Class.forName(clazz).newInstance();
	       System.out.println(id);
	       System.out.println(clazz);
	       beans.put(id, o);
	       
	       for(Element propertyElement : (List<Element>)element.getChildren("property")) {
	    	   String name = propertyElement.getAttributeValue("name"); //userDAO
	    	   String bean = propertyElement.getAttributeValue("bean"); //u
	    	   Object beanObject = beans.get(bean);//UserDAOImpl instance
	    	   
	    	   String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
	    	   System.out.println("method name = " + methodName);
	    	   
	    	   Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
	    	   m.invoke(o, beanObject);  // service的实例、 UserDAOImpl的实例
	       }
	       
	       
	    }  
	  
	}

	public Object getBean(String id) {
		return beans.get(id);
	}

}

最后的测试类:

import org.junit.Test;

import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User;
import com.bjsxt.spring.BeanFactory;
import com.bjsxt.spring.ClassPathXmlApplicationContext;

public class UserServiceTest {

	@Test
	public void testAdd() throws Exception {
		BeanFactory applicationContext = new ClassPathXmlApplicationContext();
		
		UserService service = (UserService)applicationContext.getBean("userService");

		User u = new User();
		u.setUsername("zhangsan");
		u.setPassword("zhangsan");
		service.add(u);
	}

}

这里写图片描述
依赖注入DI:userService里面userDao的属性是依赖容器来帮我们注入进来的,而不是写死的。
控制反转IOC:原来userDao是有当前类自己控制的,现在由容器帮忙控制,由运行上下文spring帮控制。好处:降低了耦合性,再者用配置文件注入修改起来方便而且灵活,反转到容器那里去了。

3.	IOC容器
    a)	实例化具体bean
    b)	动态装配
4.	AOP支持
    a)	安全检查
    b)	管理transaction

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
建议使用ApplicationContext(接口,bean factory 的子接口)还能有 生命周期等功能。。---细节要记住

注入的方式:
1、set 2、构造方法(用的不多)。 一般是set注入

spring注入类型,

5.	<bean 中的scope属性  bean的声明周期。。这个比较重要,其实也就一句话的事儿
  a)	Spring_0600_IOC_Bean_Scope
  b)	singleton 单例
  c)	proptotype 每次创建新的对象

<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" scope="single"/> 
scope="single"  -- 单例 对象1==对象2 true
scope="prototype" -- 多例 对象1==对象2 false

7.自动装配
@Component:就是把这个类初始化了。
@Resource:就是要注入哪个,默认是byName的方式

要注解的话,要先配置一个<context:annotation-config/>  配置了这句话后spring会初始化四个bean
spring注解是注解在我们源码上的,必须要有个东西去识别它,什么东西呢?就是初始化的四个bean去帮我们识别。
10.	@Autowired ---  这个写在set上,表示把userDAO注入进来。和xml效果一样
a)	默认按类型by type。。
b)	如果想用byName,使用@Qulifier
c)	写在private field(第三种注入形式)(不建议,破坏封装)
d)	如果写在set上,@qualifier需要写在参数上..指定注入那个名字的bean
11.	@Resource(重要)(用到set方法上,后面加名字,指定用的是哪个)
a)	加入:j2ee/common-annotations.jar   它是属于j2ee的
b)	默认按名称,名称找不到,按类型
c)	可以指定特定名称
d)	推荐使用
e)	不足:如果没有源码,就无法运用annotation,只能使用xml
12.	@Component @Service @Controller @Repository  -- spring会识别这四个,都当成是一个组件
用@Component要加上<context:compontent-scan base-package="...包名">去扫描所有的组件,也就是@Component
@Component(用在类上) -- 把这个类放到容器里,key就是这个类的名字,value就是生成的对象。也可以指定名字
写了@Component就不用在xml中配置了。那userService也可以加一个@Component,那它也不用在xml中配了。
@Component(value = "userDAOImpl")对应的@Resource(name = "userDAOImpl")

a)	初始化的名字默认为类名首字母小写
b)	可以指定初始化bean的名字
13.	@Scope
14.	@PostConstruct = init-method; @PreDestroy = destroy-method;

#####AOP:
加日志的业务逻辑思路:
1、继承。 不太好,因为继承太不灵活了。我从你继承了,就不能从其他类继承了,再个如果父类改了,子类也要跟着改,耦合性太强了。不好。
2、聚合。这种方式可以。在设计模式里,很多时候都用聚合代替了继承。
小插曲:IPO的意思,把公家的变成自己的。
JDK要想实现一个动态代理的话,这个类必须得实现一个接口,否则JDK是产生不了动态代理的。但是hibernate能产生,就算没有实现接口,hibernate也能产生动态代理,它是通过修改二进制码实现的。
补充动态代理的一点儿东西:
使用的过程:(产生的过程比较复杂,这里先不说了)
动态代理的应用场景:做权限,加日志,做审查(效率的检查),事务(可以在方法之前开启事务,方法之后提交事务,这样的话就不用自己写了),还可以做统一异常处理。也是面向切面编程的应用场景,非常灵活。spring的实现就是使用了JDK的动态代理,前提是这个被代理类要实现一个接口,不过就算没实现接口,spring也可以产生动态代理,它用的是CGLIB帮你产生的。
动态代理的任意方法的执行前,都可以自动的加上自己的业务逻辑。
再说一次使用JDK动态代理的过程:1、首先做一个被代理对象target出来,然后把它交给handler,代理调用的时候就知道要调用哪个被代理对象的方法了,2、然后使用newProxyInstance()来产生我们需要的代理对象。这个方法有三个参数,第一个参数是classloader,必须和被代理对象的classloader一样才行、第二个参数是它所实现的target.getClass().getInterfaces()。被代理对象实现了一个接口,产生的代理对象使用组合的方式,那它也要实现同样的接口。第三个参数是把handler传进去。。

spring使用动态代理的方式:一是annotation的方法二是用xml的方式。
######annotation方式的AOP

需要在beans.xml文件中加入<aop:aspectj-autoproxy/>,表示spring会帮我们去产生代理。意思是只要在spring的容器启动过程之中,扫描到了有个类需要产生代理(也就是使用了@Aspectj注解),它就会帮你产生代理。
内部实现是aspectj来实现的,aspectj是一个专门用来实现代理的框架。spring使用了它。

//注意这些类是从哪个包下面的。
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogInterceptor {
	//-- 关于切入点的语法,记住这一个就行这个包内任何类的任何方法,返回值是任何类型
	@Pointcut("execution(public * com.bjsxt.service..*.add(..))") 
	public void myMethod(){};//这个方法名就是 切入点集合的名字。。以起方法名的形式给切入点集合起了个名字
	
	//-- 方法执行之前先执行这段方法。被代理的对象必须被spring管理起来
	//
	@Before("myMethod()") 
	public void before() {
		System.out.println("method before");
	}
	
	@Around("myMethod()")
	public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("method around start");
		pjp.proceed();
		System.out.println("method around end");
	}
	
}

######XML方式的AOP
用别人的切面逻辑的时候,只能用XML
因为别人的切面逻辑并没有写出在哪个方法上加(也就是没有@Pointcut这种逻辑,它事先也不知道往哪个方法上加啊。),你也不好往源码上加,所以这个时候就只能用XML。
所以spring的话,IOC的时候用annotation方便。 AOP就用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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	<context:annotation-config />
	<context:component-scan base-package="com.bjsxt"/>

	<bean id="logInterceptor" class="com.bjsxt.aop.LogInterceptor"></bean>
	<aop:config>
		
		<aop:aspect id="logAspect" ref="logInterceptor">
			<aop:before method="before" pointcut="execution(public * com.bjsxt.service..*.add(..))" />
		</aop:aspect>
		

	</aop:config>

</beans>

######spring datasource
spring的数据源怎么配,?有c3p0,dbcp等。下面讲的是dbcp(数据库连接池)
JDK的java.sql包下有个接口叫DataSource。它有个方法getConnecttion(),就是拿connection的。为啥设计一个接口,因为拿到connection的方式有很多,它只需要定义接口让别人实现即可。也就是sun定义了一接口,让别人去实现。
dbcp – database connection pool数据库连接池的意思
怎么配?
这里就涉及到IOC的应用了。可以把datasource注入到DAOImpl里面。写一个datasource的接口,然后通过getConnecttion()方法拿到connection。以前的做法是加载驱动,获得连接,现在是写在xml中,用IOC注入。

<?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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	<context:annotation-config />
	<context:component-scan base-package="com.bjsxt" />

	<!-- 方法一:
		<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		
		
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/spring" />
		<property name="username" value="root" />
		<property name="password" value="bjsxt" />
		</bean>
	-->

	<bean  方法二:  方法一和方法二用的都是dhcp的数据库连接池
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>classpath:jdbc.properties</value>
		</property>
	</bean>

	<bean id="dataSource" destroy-method="close"
		class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName"
			value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

	<bean id="sessionFactory"  方法三:
	<!--  
	//这里的sessionFactory是spring的,而不是hibernate的,因为hibernate的sessionFactory是一个接口,这里spring是对它的实现。。这里要把方法二的datasource注入给它。。。
//这里在DAOImpl里面就直接注入AnnotationSessionFactoryBean就可以了,因为datasource已经注入到AnnotationSessionFactoryBean了。。
如何注入:在DAOImpl的set方法上写@Resource,默认是byName。
-->
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="annotatedClasses"> 
			<list>
				<value>com.bjsxt.model.User</value> //这里表示哪些类是hibernate的实体类,在这里配
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
	</bean>
</beans>
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=bjsxt
<property name="packagesToScan">
			<list>
				<value>com.bjsxt.model</value> 上面的配置可以通过这个标签来优化。。
				
			</list>
</property>

######整合hibernate
这部分在spring的官方文档里面也有些。
首先是sessionfactory怎么构建,(回忆一下,SessionFactory对象就是 读取对象/关系映射文件 xxx.hbm.xml ),SessionFactory只需要一个就可以了,而spring管理的对象默认情况下就是一个单例,所以SessionFactory很适合交给spring去管理。。
关于整个hibernate的xml如何配,见上文,方法三。
DAOImpl里面怎么写,见下:

@Component("u") 
public class UserDAOImpl implements UserDAO {

	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	
	@Resource
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public void save(User user) {
		
		//Hibernate
		//JDBC
		//XML
		//NetWork
		System.out.println("session factory class:" + sessionFactory.getClass());
			Session s = sessionFactory.openSession();
			s.beginTransaction();
			s.save(user);
			s.getTransaction().commit();
		System.out.println("user saved!");
		//throw new RuntimeException("exeption!");
	}

}

初步总结spring、hibernate的整合顺序:

2.	Spring整合Hibernate
a)	<bean .. AnnotationSessionFactoryBean>
i.	<property dataSource
ii.	<annotatedClasses              ----- 拿到sessionfactory,里面包含了datasource,标明哪些类需要加注解
b)	引入hibernate 系列jar包
c)	User上加Annotation     -----  @Entity等
d)	UserDAO或者UserServie 注入SessionFactory 
e)	jar包问题一个一个解决

######整合过程中的事务管理 2个方式(说明一下tx就是transaction的意思)
spring的声明式事务就是AOP的运用。。
重点是要去理解,然后配什么去查文档即可。。。具体思路可以去看马士兵的spring.doc笔记
spring对各种各样的ORM框架都支持事务管理,现在看看hibernate的。
关于事务, 一定要找到它的起点和终点(专业名词叫事务的边界),应该放在service层,service会调用多个dao。如果写在DAO层,那意味着service的两个操作分别在两个事务里面,那一个dao抛异常,另一个dao是不会回滚的,也就是service只完成了一般的操作。。所以事务的边界应加在业务处理层。
那事务怎么加呢??
在一个方法上加事务,只需要加一个注解即可。另外在spring配置文件里面要声明一个tx,见下:表示是注解驱动的事务管理。

<tx:annotation-driven transaction-manager="txManager"/>//这里表示是注解驱动的事务管理
<bean id="txManager"
		//它要通过一个connection来管理事务啊,(如果是跨数据库,那就要用JTA来管理事务)。
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">  //这是一个切面类。
		//怎么告诉它这个connection是谁呢? 就是把sessionFactory给注进去,而sessionFactory里又注入了source,所以就拿到了数据库连接
		//另外HibernateTransactionManager在进行事务管理的时候需要hibernate的一些配置,这些配置就是从sessionFactory中来的。
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

以上配置完之后,事务的处理就交给txManager了,它也是一个bean啊。 关系:datasource注入到sessionfactory,sessionfactory注入到txManager。。
然后就可以在service方法上声明了,这里面其实就是AOP的实现。service方法开始前beginTransaction,方法结束就transaction commit,有异常,它自动的rollback。
所以整合之后hibernate的session要用getCurrentSession,因为service方法开始的时候事务管理器生成了session。如果不指定,默认的上下文是thread。
如果中间抛出一个runtimeexception,那事务会回滚。

事务传播特性(有很多种,默认是required):propagation_required。。required的意思:
例子程序中,userTest里面的testAdd()去调用service里面带有事务的add()。。。如果别人(testAdd)调用我这方法(加了事务的方法add),如果已经有了事务了,就用原来那个,把自己当作事务的一部分加进去就可以了,如果没有就创一新的。。
以上就是spring对于hibernate的事务管理。

XML的事务配置如下:
至于用XML还是annotation,看情况。但是大多数还是XML配置,因为它可以同时配置好多方法。

<aop:config>
		<aop:pointcut id="bussinessService"
			expression="execution(public * com.bjsxt.service..*.*(..))" /> 搞个切面,在service的时候加
		<aop:advisor pointcut-ref="bussinessService"
			advice-ref="txAdvice" /> 通过这个指明一个事务。
	</aop:config>

	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="getUser" read-only="true" />只读表示这里不能做修改操作,提高性能的。
			<tx:method name="add*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>

spring针对hibernate的使用上,有一些简单的封装,主要是hibernateTemplate,hibernateCallback,作用是简化编程。。
这里面有个设计模式叫,模版方法。。
i. 设计模式:Template Method
ii. Callback:回调/钩子函数
iii. 第一种:(建议)

  1. 在spring中初始化HibernateTemplate,注入sessionFactory
  2. DAO里注入HibernateTemplate
  3. save写getHibernateTemplate.save();

这里的话,就不用sessionfactory了,因为sessionfactory已经交给hibernateTemplate了。
这个时候就不要s.save了。直接hibernateTemplate.save就行了。这里就不要去管session了。
这里写图片描述

##孔浩的spring
这里写图片描述

1、引包
2、spring读取所有的文件都是在一个工厂里面读,这个工厂通过xml来配置,
原先创建类new的方式,这样依赖于实现类。

##慕课网 探秘Spring AOP
###1、5中advice注解

advice 描述的是你想在方法的执行之前,执行之后,或者是前后 要加入你要织入的代码。
主要是描述织入的时机,因此可以分为这5个部分。。
这里写图片描述

这点东西,在马士兵的spring笔记里面都有。。。

###2、spring AOP实现原理解析
####1、
大致内容如下:
AOP的代理实现:JDK的和CGLIB的。。。

这里写图片描述

spring AOP 的织入时机是 运行时 织入的。
那么 运行时织入是怎么实现的???答案:代理对象来实现的。。

####2、代理源码
静态代理
缺点:如果目标类有100个方法,那代理类需要对这100个方法进行委托,但是这100个方法前后需要执行的逻辑又都是一样的,所以就重复了。 所以产生了动态代理技术。

动态代理分为两大类:基于接口代理和基于继承代理。。他俩的代理分别是JDK代理和Cglib代理。。
#####JDK代理,实现源码:


1、首先调用newProxyInstance
Proxy.newProxyInstance(
                Subject.class.getClassLoader(),
                new Class[]{Subject.class},  //注意这个接口的获取
                new JdkProxySubject(new RealSubject()));
2、newProxyInstance会去调用getProxyClass0
		/*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);
getProxyClass0方法是去“寻找或者是生成指定的代理类”,它其实是先从缓存里面取,如果缓存没有它就去生成一个(看源码的方法注释),
这个缓存是从ProxyClassFactory中找,如果没有就生成。

3、getProxyClass0是从ProxyClassFactory(内部类)中生成Proxy代码的。
ProxyClassFactory生成的主要代码在apply方法,方法里找到接口的class对象,
Class<?> interfaceClass = Class.forName(intf.getName(), false, loader);
然后往下一步一步的进行 字节码的生成,
			/*
             * Generate the specified proxy class.
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass( //看到这里是调用了ProxyGenerator来生成代码的
                proxyName, interfaces, accessFlags);


4、ProxyClassFactory又是调动了ProxyGenerator(类)来生成代码
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
        final byte[] var4 = var3.generateClassFile();
        if (saveGeneratedFiles) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    try {
                        int var1 = var0.lastIndexOf(46);
                        Path var2;
                        if (var1 > 0) {
                            Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                            Files.createDirectories(var3);
                            var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                        } else {
                            var2 = Paths.get(var0 + ".class");
                        }

                        Files.write(var2, var4, new OpenOption[0]);
                        return null;
                    } catch (IOException var4x) {
                        throw new InternalError("I/O exception saving generated file: " + var4x);
                    }
                }
            });
        }

        return var4;
    }



5、newInstance()。 最后生成字节码之后用反射new一个实例。

#####Cglib
有两点需要注意:
1、Cglib是通过继承的方式来实现代理类的,
2、Cglib是通过Callback(intercetor)的方式来织入我们想要的代码

MethodInterceptor和JDK的InvocationHandler很类似,同样是方法去反射调用目标对象的方法 。
这里写图片描述
这里写图片描述

这里写图片描述

####3、spring如何实现代理
#####源码
spring是如何创建AOP代理类的:
这里写图片描述

所以:总结:
这里写图片描述

如何强制使用Cglib代理:
这里写图片描述

#####责任链模式

多个AOP作用于一个对象的时候,他们是如何叠加到一起的。。 这里用到了 责任链模式。。
这里写图片描述

代码见码云。。。。com.reflect.dynamicProxyFromMukeWang.chain

#####spring AOP应用源码解析
这里写图片描述

有点复杂,自行看视频去。。

流程
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值