spring
作者:Yjanuary
@基本配置
<bean id=" " class=" "></bean>
<bean> :配置需要创建的对象
id :用于之后从spring容器获得实例时使用的
class :需要创建实例的前限定名称
@xml解析:
classPathXmlApplicationContext :用于加载,解析classpath下xml
@setter注入
创建service
<bean id="bookServiceId" class="">
<property name=" bookDao" ref="bookDaoId "></property>
</bean>
创建dao实例
<bean id=" dao实例" class=" "></bean>
模拟spring执行过程
创建service实例:
BookService bookService = new BookServiceImpl() IOC
创建dao实例 :
BookDao bookDao = new BookDaoImpl() Ioc
将dao设置给service :
bookService.setBookDao(bookDao) di
property 用与进行属性注入
name :bean的属性名 ,通过setter方法获得
setBookDao ## >BookDao ##> bookDao
ref :另一个bean的id值的引用
BeanFactory:用于生成任意bean,采用延迟加载,第一次getBean时才会初始化Bean
ApplicationContext :是BeanFactory的子接口,功能更强大
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(xmlPath));
@实例化方式
3种实例化方式:默认构造,静态工厂,实例工厂
1:默认构造 :必须提供默认构造
<bean id=" " class=" ">
2:静态工厂:用于生成实例对象,所有的方法必须是static
3:工厂
public class MyBeanFactory{
public static UserService createService(){
return bew UserServiceImpl();
}
}
spring配置
<bean id="userServiceId" class="com.shikun.inject" factory-method="createService">
</bean>
@Bean 种类
1:普通bean :
<bean id=" " class=" ">
2:FactoryBean:是一个特殊的bean,具有工厂生成对象能力,只能生成特定的对象
bean必须使用FactoryBean接口,此接口提供方法getObject()用于获取特定bean
3:BeanFactory 和 FactoryBean对比
BeanFactory:工厂,用于生成任意bean
FactoryBean:特殊bean,用于生成另一个特定的bean,例如:ProxyFactoryBean,此工厂用于生产代理对象
@作用域 scope
<bean id="userServiceId" class=" " scope="prototype"></bean>
取值
singleton 单例,默认值
prototype 多例,每执行一次getBean将获得一个实例
@生命周期
初始化和销毁
<bean id=" " class="" init-method="初始化方法名称" destroy-method="销毁的方法名称"></bean>
public class UserServiceImpl implements UserService{
public void myInit(){
System.out.println("初始化");
}
public void myDestroy(){
System.out.println("销毁");
}
}
备注:1:容器必须close,销毁方法执行 , applicationContext.close();
2:必须是单例的
@BeanPostProcessor后处理Bean
spring提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给
spring容器,spring容器将自动执行,在初始化方法前执行before(),z
在初始化后执行after(). 配置,生成代理对象
关键代码:
return Proxy.newProxyInstance(
MyBeanPostProcessor.class.getClassLoader(),
bean.getClass().getInterfaces(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy,Method method,Object[] args)
throws Throwable{
System.out.println("-----开启事务");
//执行目标方法
Object obj = method.invoke(bean,args);
System.out.println("------提交事务");
return obj;
}});
}
}
配置文件
<bean class="com.shikun.lifecycle.MyBeanPostProcessor"></bean>
MyBeanPostProcessor后处理bean作用某一个目标类,通过beanName进行控制作用一个
@属性依赖注入
手动装配:一般进行配置信息都采用手动
基于xml装配:构造方法,setter方法,基于注解装配
自动装配:Struts和spring整合可以自动装配
byType :按类型装配 byName :按名称装配 constructor:构造装配
auto :不确定装配
1:构造方法注入:
<constructor-arg name=" " value=" " ref=" ">
name:参数的名称 value:设置普通数据 ref:引用数据,一般是另一个bean id值
2:setter方法注入
<property name=""ref="另一个bean"></property>
3:p命名空间
<bean
p:属性名="普通值" p:属性名-ref="引用值">
</bean>
4:SpEL
对property进行统一编程,所有的内容都是用value
<property name="" value="#{表达式}">
{beanId} :另一个bean引用
{beanId.propName} :操作数据
{beanId.toString()} :执行方法
{T(类).字段|方法} :静态方法或字段
<bean id="customerId" class="">
<property name="cname" value="#{cutomerId.cname?.toUpperCase()}:></property>
<property name="pi" value="#{T(java.lang.Math).PI}></property>
</bean>
5:集合注入
集合的注入都是给<、property>添加子标签
数组:<array> List:<list> Set:<set> Map:<map>,map存放k/v键值对,使用<entry>描述
properties:<props> <prop key=""></prop>
普通数据:<value> 引用数据:<ref>
<bean id="collDataId" class="com.itheima.f_xml.e_coll.CollData" >
<property name="arrayData">
<array>
<value>DS</value>
<value>DZD</value>
<value>屌丝</value>
<value>屌中屌</value>
</array>
</property>
<property name="listData">
<list>
<value>于禁</value>
<value>高富帅</value>
<value>张子凡</value>
<value>曾小贤</value>
</list>
</property>
<property name="setData">
<set>
<value>牛</value>
<value>吗</value>
<value>狗</value>
</set>
</property>
<property name="mapData">
<map>
<entry key="jack" value="杰克"></entry>
<entry>
<key><value>rose</value></key>
<value>肉丝</value>
</entry>
</map>
</property>
<property name="propsData">
<props>
<prop key="高富帅">嗲</prop>
<prop key="白富美">吧</prop>
<prop key="男屌丝">波</prop>
</props>
</property>
</bean>
6:装配Bean基于注解
注解:就是一个类,使用@注解名称
1:@Component取代<bean class="">
@Component("id") 取代<bean id="" class="">
2:web开发,提供三个注解取代<bean class="">
@Repository:dao层
@Service:service层
@Controler:web层
3:依赖注入,给私有字段设置,也可以给setter方法设置
普通值:@Value("")
引用值:方法1:按照类型注入
@Autowired
方法2:按照名称注入
@Autowired
@Qualifier("名称")
方法3:按照名称注入
@Resource("名称")
4:生命周期
初始化:@PostConstruct
销毁:@preDestroy
5:作用域
@Scope("prototype")多例
@注解
1:扫描含有注解的类:<context:component-scan base-package="..">
<context:annotation-config>
一般两个注解不一起使用
注解1:扫描含有注解类
注解2:只在xml和注解混和使用时,使注入注解生效
2:常用的注解
@Component 组件,任意bean
WEB
@Controler web层
@Service service层
@Repository dao层
注入 字段或setter方法
普通值:@value
引用值
类型:@Autowired
名称1 :@Autowired @Qualifier("名称")
名称2 :@Resource("名称")
作用域:@Scope("prototype")
生命周期
初始化:@PostConstruct
销毁方法: @PreDestroy
@AOP
1:AOP(面向切面编程):采用横向抽取机制,取代了传统纵向继承体系重复性代码
2:实现原理:aop底层采用代理机制进行实现
接口+实现类:spring采用jdk的动态代理proxy
实现类:spring采用cglib字节码增强
3:AOP术语:target:目标类
Joinpoint:连接点是指那些可能被拦截的方法
PointCut:切入点:已经被增强的连接点
advice:通知/增强,增强代码
Weaving:织入,是指把增强advice应用到目标对象target来
创建新的代理对象proxy的过程
proxy:代理类
Aspect:切面,是切入点pointcut和通知advice的结合
一个线是一个特殊的面
一个切入点个一个通知,组成一个特殊的面
@jdk动态代理
proxy.newProxyInstance:
参数1:loader,类加载器,动态代理类,运行时创建
任何类都需要类加载器将其加载到内存
参数2:class[] interfaces 代理类需要实现的所有接口
参数3:InvocationHandler 处理类,接口,必须进行实现类
一般采用匿名内部类,提供invoke方法,代理类的每一个方法
执行时都将调用一航次invoke
参数1:Object proxy:代理对象
参数2:Method method :代理对象当前执行的方法的描述对象
参数3:Object[] args:方法实际参数
UserService proxService=(UserService)Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
userService.getClass().getInerfaces(),
new InvocationHandler(){
public Object invoke(Object proxy,Method method,
Object[] args) throws Throwable{
Object obj = method.invoke();
}
});
return proxService;
}
@CGLIB字节码增强
导入jar包:
核心:hibernate-distribution-3.6.10.Final\lib\bytecode\cglib\cglib-2.2jar
依赖:struts-2.3.15.3\apps\strurs2-blank\WEB-INF\lib\asm-3.3.jar
//核心类
Enhancer enhancer = new Enhancer();
//确定父类
enhancer.setSuperclass();
//设置回调函数,MethodInterceptor接口 等效jdk InvocationHandler接口
intercept() 等效jdk invoke()
参数4 :methodProxy 方法的代码
enhancer.setCallback(new MethodInterceptor(){
public Object intercept(Object proxy,Method method,Object[] args,
MethodProxy methodProxy) throws Throwable{
Object obj = method.invoke(userService,args);
//执行代理类的父类,执行目标类
methodProxy.invokeSuper(proxy,args);
}
});
//创建代理
UserServiceImpl proxService =(UserServiceImpl)enhancer.create();
return proxService();
}
@AOP联盟通知类型
spring按照通知Advice在目标类方法的连接点位置
前置通知 org.springframework.aop.MethodBeforeAdvice
在目标方法执行前实施增强
后置通知 org.springframework.aop.AfterRetuningAdvice
在目标方法执行后实施增强
环绕通知 org.aopalliance.intercept.MethidInterceptor
在目标方法执行前后实施增强
异常抛出通知 org.springframework.aop.ThrowsAdvice
在方法抛出异常后实施增强
引介通知 org.springframework.aop.IntroductionInterceptor
在目标类中添加一个新的方法和属性
@spring编写代理:半自动
1:切面类:切面类中确定通知,需要实现不同接口,接口就是规范
采用环绕通知 :实现 MethodInterceptor
2:spring配置
创建代理类:使用工厂bean FactoryBean,底层调用getObject(),返回特殊bean
ProxyFactoryBean:用于创建代理工厂bean,
interfaces:确定接口类
target:确定目标类
interceptorNames:通知 切面类的名称,类型String[]
optimize:强制使用cglib:<property name="optimize" value="true"></property>
底层机制
如果目标有接口,采用jdk动态代理
如果没有接口,采用cglib字节码增强
如果声明optimize =TRUE ,无论是否有接口,都采用cglib
<bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="com.shikun.factory_bean.UserService"></property>
<property name="target" ref="userServiceId"></property>
<property name="interceptorNames" value="myAsoectId"></property>
</bean>
@spring aop编程 :全自动
1:spring 配置
aop编程:使用<aop:config>进行配置
proxy-target-class="true"声明使用cglib代理
<aop:pointcut>:切入点,从目标对象获得具体方法
<aop:advisor>:特殊的切面,只有一个通知和一个切入点
切入点表达式:execution(*com.shikun.spring_aop.*.*(..))
选择方法 返回值任意 包 类名任意 方法名任意 参数任意
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(*com.shikun.spring_aop.*.*(..))"id="myPointCut"/>
<aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/>
</aop:config>
@ApsectJ
1:ApectJ是一个基于Java语言的AOP框架
2:通知类型:
before:前置通知:在方法执行前执行,如果通知抛出异常,阻止方法运行
afterReturning:后置通知:方法正常返回后执行
around:环绕通知:方法执行前后分别执行,可以阻止方法的执行,必须手动执行目标方法
afterThrowing:抛出异常通知,方法抛出异常后执行
after:最终通知,方法执行完毕后执行,无论方法中是否出现异常
3:基于xml
spring配置
<aop:aspect>将切面类,声明切面,从而获得通知,ref:切面类应用
<aop:pointcut>声明一个切入点,所有的通知都可以使用,expressiong切入点表达式
<aop:config>
<aop:aspect ref="myAspectId">
<aop:pointcut expression="execution(*com.shikun.aspect.xml.UserServiceImpl.*(..))" id="myPointCut"/>
<aop:after method="myAfter" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
4:基于注解
1:扫描注解类:
<context:component-scan base-package="com.shikun.aspect.anno"></context:component-scan>
2:替换aop
必须进行aspectj自动代理
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
3:aop注解总结
@Aspect:声明切面,修饰切面类,从而获得通知
@Before:前置
@AfterReturning:后置
@Around:环绕
@AfterThrowing:抛出异常
@After:最终
@PointCut:修饰方法
@JdbcTemplate
1:spring提供用于操作JDBC工具类
2:配置
<bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSourceId"></property>
</bean>
3:使用JdbcDaoSupport
dao继承JdbcDaoSupport,之后只需要注入数据源,底层将自动创建模板
<bean id="userDaoId" class="com.shikun.jdbcdaosupport.userDao">
<property name="dataSource" ref="dataSourceId"></property>
</bean>
4:properties文件
1:jdbc:driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring
jdbc.user=root
jdbc.password=123
2:spring配置
加载配置:classpath:前缀表示src下,在配置文件之后通过${key}获得内容
<context:property-placeholder location="classpath:com/shikun/properties/jdbcInfo.properties/>
创建数据源 c3p0
<bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.pasword}"></property>
</bean>
@事务管理
1:事务:一组业务操作ABCD,要么全部成功,要么全部不成功
2:特性:ACID 原子性:整体;一致性:完成; 隔离性:并发; 持久性:结果;
3:隔离问题:
脏读:一个事务读到另一个事务没有提交的数据
不可重复读:一个事务读到的另一个已提交的数据
虚读(幻读):一个事物读到另一个事务已提交的数据
4:隔离级别:
read uncommitted:读未提交
read committed :读已提交
repeatable read :可重复读
serializable:串行化
5:事务操作:1:setAutoCommit 2:mysql事务操作:Savepoint
6:三个顶尖接口:
PlatformTeansactionManager:平台事务管理器,spring要管理事务,必须使用
事务管理器,进行时往往配置时,必须配置事务
TransactionDefinition:事务详情(事务定义,事无属性),spring用于却动事务具体
详情,例如:隔离级别,是否只读等
TransactionStatus:事务状态,spring用于记录当前事务运行状态。例如:是否有保存点
@PlatformTransactionManager:事务管理器
1:常见的事务管理器
DataSourceTransactionManager,jdbc开发室事务管理器,采用JdbcTemplate
HibernateTransactionManager,hibernate开发时事务管理器,整合hibernate
2:api详解
TransactionStatus getTransaction(TransactionDefinition definition),事务管理器,通过
“事务详情”,获得“事务状态”,从而管理事务
void commit(TransactionStatus status) 根据状态提交
void rollback(TransactionStatus status) 根据状态回滚
TransactionStatus:
isNewTransaction(): 是否是新的事务
hasSavepoint(): 是否有保存点
setRollbackOnly():设置回滚
isRollbackOnly():是否回滚
flush():刷星
isCompleted():是否完成
@TransactionDefinition:
1:传播行为:在两个业务之间如何共享事务
PROPAGATION_REQUIRED,required,必须【默认值】,支持当前事务
A如果有事务,B将使用该事务
如果A没有事务,B将创建一个新的事务
PROPAGATION_SUPPORTS,supports,支持
支持当前事务,A如果有事务,B将使用该事务
如果A没有事务,B将以非事务执行
PROPAGATION_MANDATORY,mandatory ,强制
支持当前事务,A如果有事务,B将使用该事务
如果A没有事务,B将抛出异常
@整合Junit
1:Junit通知spring加载配置文件
2:让spring容器自动进行注入
@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration(locations="classpath:application.xml")
public class TestApp{
@Autowired //与Junit整合,不需要在spring xml 配置扫描
private AccountService accountService;
@Test{
public void demo1(){
accountService.transfer("jack","rose",1000);
}
}