传智播客JAVA培训spring学习总结(2010520)
通过一天的努力,终于对spring有了信心呵!多谢黎老师录的视频,深入浅出,师者,不愧为良师!现在想来有点后怕,如果当初没有一些基础就来冲刺班,一定会很难度,这两天的项目因为spring的缘故自己拖下了,还得继续的努力下去。
来这儿这么多天了,说实在的,我没有一天是过得轻松的,天天都是在学力的压力中成长。今天我们班又有一个同学上班去了6.5K,虽然是3G项目(我的方向不是这个),我还是挺羡慕他们,能这么早就摆脱了就业的压力,待遇还不错,可是我呢?还在j2ee的路上拼搏,2个月后,一切都见真效了,我希望的我前途是光明的,也希望天下好人都一样有一个好的前途。努力始终会有机会的。
我现在写总结的目地在于,特别是这几个框架,把所有的心得体会,以及知识点都写上,是为了以后工作中,或者是遇到什么问题了,可以回来查,因为是自己写的,所以理解起来比别人更好理解,人的记忆都有限制,不可能把所有的东西都记下,所以啊,写笔记,是非常有用的。(图片来自于讲义,文字来自于对老师的话的总结)
1.如何使用spring
必须的JAVA文件
a) Spring.jar
b) Commons-logging.jar
如果使用切面编程,还需要下列文件:
c) aspectj/Aspectjweaver.jar
d) aspectj/Aspectjrt.jar
e) Cjlib/cjlib-nodep-x.x.jar
如果使用jsr-250的注解时需要添加下列文件:
f) /j2ee/Common-annotations.jar
Spring包文件结构:
Spring的配置文件:
1.名字可以随意取
2.可以有多个配置文件(可用数组方式)
实现软件解藕,采用接口的编程方式。
配置文件的元素及属性
<bean id="唯一名字,不能包含特殊字符" name="也代表名字,但是可经有特殊字符" init-method="指定初始化方法" destory-method="指定bean被销毁的时候执行的方法">
Bean是什么时候被销毁的呢?默认是在容器停止时,才会销毁。但同样我们可以采用这样一个抽象类来正常关闭:
AbstractApplicationContext ctx = ;
Ctx.close;可以正常关闭。
<!-- 普遍方式 -->
<bean id="personService" class="cn.itcast.spring.service.impl.PersonServiceBean" />
<!-- 工厂静态方法模式 -->
<bean id="personService2" class="cn.itcast.spring.service.impl.PersonServiceBeanFactory"
factory-method="createPersonServiceBean" />
<!-- 工厂方法 -->
<bean id="beanFactory" class="cn.itcast.spring.service.impl.PersonServiceBeanFactory"/>
<bean id="personService3" factory-bean="beanFactory" factory-method="createPersonServiceBean2"/>
Bean 的使用域:
默认为单例模式。默认是在容器初绍化时初始化。但可以通过lazy-init="true"进行更改。但在实际应用中大多采用的通过不采用。
DI(注入)
注入的方式:
1.set方法 bean可以被我个ref使用
2.构造方法
3.内部bean 只能提供一个服务
如何为基本类型注入值呢?直接:
<property name="属性名" value="值" />
注入集合,properties等 例子如下:
<bean id="personService" class="cn.itcast.spring.service.impl.PersonServiceBean" >
<property name="personDao" ref="personDao"/>
<property name="id" value="1"/>
<property name="name" value="pingping"/>
<property name="set">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
<property name="list">
<list>
<value>11</value>
<value>22</value>
<value>33</value>
</list>
</property>
<property name="prop">
<props>
<prop key="a">1</prop>
<prop key="b">2</prop>
<prop key="c">3</prop>
</props>
</property>
<property name="map">
<map>
<entry key="a" value="a" />
<entry key="b" value="a" />
<entry key="c" value="a" />
</map>
</property>
</bean>
注入-手工装配
1.以上是手工装配的方式的一种:在xml文件中进行注入。但是在实际的开发过程中bean有成百上千,所以配置文件可能非常的多。我们就可以采用下一种方式:注解
2.但是还可以采用注解的方式进行注入。
a) 首先添加
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 采用注解的方式 -->
<context:annotation-config/>
</beans>
@Autowired默认按类型进行装配。这是spring提供的,默认按类型进行装配。可以手动设置成按名称注入,加入:@Autowired @Qualifier("personDao")。
@Resource默认按名称进行装配,如果按名字找不到,在按类型。其有一个name属性。如果没有指定,就按类中指定的名字,进行查找。建议使用。这个即可用在属性上,也可以用到set方法上。
传智播客注解原理:
1.定义一个注解,该注解可以放在属性和方法上。定义一个属性name。
2.有一个处理器。
a) 根据方法:
1.循环所有的bean对象
2.获取每一个bean对象
3.如果存在,获得属性
4.循环属性,获得其“写”方法。判断该方法是否存在注解是存在指定的注解。
5.判断该注解是是否有name属性。如果有,取出name属性。根据name属性查找 装bean的集合中的 容器是否有该name对应的对象,有则赋值。如果没有,则取得属性的名称,用属性名称去集合中取bean, 赋值。如果都没有寻找到,就按类型去寻找。循环所有的bean判断bean的类型是否和name所对应的 bean的类型是否匹配,如果有,则赋值。
B).根据属性
同上四五步,不去找写方法,而是直接用属性去找到注解。
注入-自动装配
在bean 中设置一个属性:autowire="行为"
不建议使用(老师推荐)
通过classPath自动把组件扫描进spring容器中进行管理:
<context:component-scan base-package="扫描指定路径" />
他是怎么知道一个类是否要交给容器管理呢?这里用到了注解。在类之前组解
1.@Service 服务层 service
2.@Controller 控制层action
3.@Repository 数据访问层(dao)
4.@component 泛指组件。
目前他们的作用是一样的。但是他们是怎么知道受管理时的名字呢?相当于:<bean name=""/>,所以,他们指供了设置名字:@Service("名字"),如果没有设置时,就是类的简单名称,将第一个字符小写。当然,也是可以设置作用域的 @scope("prototype");每调用一次就产生一个新对象。指定初始化方法:在一个方法上加@PostConstruct。也可以设置销毁方法!
AOP
1.可以采用Proxy.newInstance方法来实现。Java提供
2.Cglib来实现
根据以上的理解,我猜测spring AOP 的实现的原理,应该不是采用以上的两种方式吧!
AOP概念:
采用spring AOP 进行面向切面编程:
1.采用注解的方式
定义一个切面(比较全面,以后利于查阅):定义之后,在xml中加入:<aop:aspectj-autoproxy/>,就不用理他了,自动完成。切点定义了,用在那些的地方,而在定义具体的通知表示要做的事情,此时还可以设置范围,满足条件下才可以执行。
@Aspect
public class MyInterceptor {
// service下所有包,所有类,所有方法,任何返回类型
@Pointcut("execution (* cn.itcast.aop.service.impl.PersonServiceBean.*(..))")
private void anyMethod() {}//声明一个切入点
@Before("anyMethod() && args(name)")// 可以在这里添加&&,来匹配其它的条件。比如:args(name),这儿的名字要和下面方法的名字一致.相当于要执行前面的条件的同时,同时滶参数只有一个,且为string
public void doAccessCheck(String name){
System.out.println("前置通知");
}
//同样也可以得到访求的返回值,以及例外(异常)等。
@AfterReturning("anyMethod()")
public void doAfterReturn(){
System.out.println("后置通知");
}
@After("anyMethod()")
public void doAfter(){
System.out.println("最终通知");
}
@AfterThrowing(("anyMethod()"))
public void doThrow(){
System.out.println("例外通知");
}
@Around("anyMethod()")
public Object doBaseProfiling(ProceedingJoinPoint pjp) throws Throwable{
//必须执行这个方法,如果不执行,业务bean中的方法是不会执行的.如果后面还有切面,先执行后面的
Object result = pjp.proceed();
System.out.println("环绕通知");
return result;
}
}
2.采用xml方式
<bean id="myInterceptor" class="cn.itcast.aop.service.MyInterceptor" />
<bean id="personService" class="cn.itcast.aop.service.impl.PersonServiceBean" />
<aop:config>
<aop:aspect id="asp" ref="myInterceptor">
<aop:pointcut
expression="execution(* cn.itcast.aop.service.impl.PersonServiceBean.*(..))"
id="mycut" />
<aop:before pointcut-ref="mycut" method="doAccessCheck" />
<aop:around method="doBaseProfiling" pointcut-ref="mycut"/>
</aop:aspect>
</aop:config>
特别需要注意的是:execution(* cn.itcast.aop.service.impl.PersonServiceBean.*(..)) 大有文章,要对什么方法拦截,完全在这儿控制。
问题:spring AOP 可不可以在执行一个java本身的类进行拦截呢?
SPRING+JDBC
1.配置数据源:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<!-- 连接沲初始值 -->
<property name="initialSize" value="1"/>
<!-- 连接沲最大值 -->
<property name="maxActive" value="500"/>
<property name="maxIdle" value="2"/>
<property name="minIdle" value="1"/>
</bean>
2.采用注解方式配置事务
a) 事务管理器
<!-- 事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 使用注解时要这样 -->
<tx:annotation-driven transaction-manager="txManager" />
<bean id="personService" class="cn.itcast.service.PersonServiceBean">
<property name="dataSource" ref="dataSource" />
</bean>
该bean要类头要要添加 @Transactional
把数据库的连接信息搞到另外一个文件中。
<context:property-placeholder location="classpath:jdbc.properties" />
3.Spring事务
a) Spring 开起事务之后,默认是运行期意外//unchecked会回滚。RunTimeException
b) 如果是Excption这种异常时,不会回滚。Checked不会
c) 如果我们也想要他回滚进,我们可以在方法加入:
i. @Transactional(rollbackFor=Exception.class)
d) 有一些方法不需要事务管理。不需要时,我们要怎么做呢?默认开启了事务。因为这样会影响性能。同工同酬我们可以这样做:@Transactional(propagation=Propagation.NOT_SUPPORTED)
e) 事务传播行为:
问题:如何开起一个新的事务?
数据库的隔离级别:
Spring的团队,建议采用注解配置。而现在很多公司采用xml。因为注解的方式,配置每一个方法比较容易,而采用xml的方式则,配置比较臃肿。