spring框架:
轻量级框架,javaEE的春天,当前主流框架
目标:
使现有技术更加易用,推进代码最佳实践
内容:
1、依赖注入容器
2、web集成
3、数据访问支持
4、简化Hibernate编码
5、声明式事务
6、AOP实现
IOC和DI:
IOC:其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源。作为回应,容器实时的返回资源。而应用了IOC之后,则是容器主动地将资源推送给他所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源。这种行为也被称为查找的被动形式
DI(依赖注入)----IOC的另一种表述方式:即组件以一些预先定义好的方式接受来自容器的资源注入,相对于IOC而言,这种表述更直接
为什么使用依赖注入(DI):
1、组件化的思想:分离关注点
2、依赖注入,强制将组件的构建和使用分开
IOC的操作:
1、把对象的创建交给spring进行管理
2、IOC操作两部分:
(1)IOC的配置文件
(2)IOC的注解
IOC底层原理:
IOC底层原理使用技术
(1)xml配置文件
(2)dom4j解决xml
(3)工厂设计模式
(4)反射
Spring容器:
在xml文件中通过bean节点来配置bean
在Spring IOC 容器读取 Bean 配置创建Bean实例之前,必须对它进行实例化。只有在容器实例化后,才可以从IOC容器获取Bean实例并使用
Spring提供了两种类型的IOC容器实现
1、BeanFactory:IOC容器的底层基本实现
2、ApplicationContext:提供了更多的高级特性。是BeanFactory的子接口
配置Bean基于xml:
<!-- 在IOC容器中创建HelloSpring对象 -->
<bean id="hello" class="com.jredu.entity.HelloSpring" scope="prototype"><!-- scope是选择是否单例模式 -->
<property name="name" value="奥特曼 ""/>
<property name="age" value="2000"/>
</bean>
ApplicationContext app= new ClassPathXmlApplicationContext("applicationContext.xml");
HelloSpring hello= (HelloSpring)app.getBean("hello");
bean实例化的三种方式:
(1)使用类的无参数构造创建
(2)静态工厂
(3)实例工厂创建
xml配置Bean-----依赖注入方式
1、属性注入:
属性注入即通过setter方法注入Bean的属性值或依赖的对象
属性注入使用<property>元素,使用name属性指定bean的属性名称,value属性或<value>子节点指定属性值
2、构造器注入:
通过构造方法注入bean的属性值或依赖的对象,它保证了bean实例在实例化后就可以使用
构造器注入在<constructor-arg>元素里声明属性,常用属性:name,value,type
3、接口方法注入(很少使用,不推荐)
引用Bean:
通过<ref>元素或ref属性为bean的属性或构造器参数指定对bean的引用
<bean id="addr" class="com.jredu.entity.Address">
<property name="name" value="花果山"/>
<property name="code" value="123456" />
</bean>
<bean id="ccz" class="com.jredu.entity.Person">
<property name="name" value="ccz"/>
<property name="address" ref="addr" />
</bean>
p:名称空间注入
xmlns:p="http://www.springframework.org/schema/p"
<!--c3p0连接池配置 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" p:driverClass="${jdbc.driverClassname}"
p:jdbcUrl="${jdbc.url}" p:user="${jdbc.user}" p:password="${jdbc.pwd}"
p:initialPoolSize ="${jdbc.initPoolSize}" p:maxPoolSize="${jdbc.maxPoolSize}"
/>
<bean id="jdbcTemptate"
class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"
/>
使用注解配置:
组件扫描:Spring 能够从classpath下自动扫描,侦测和实例化具有特定注解的组件
特定组件包括:
@Component:基本注解,标识了一个受Spring管理的组件
@Repository:标识持久层组件
@Service:标识服务层(业务层)组件
@Controller:标识控制层组件
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称
注入属性:
1、@Autowired根据类名自动注入属性
@Autowired注解自动装Bean
构造器,普通字段,一切具有参数的方法都可以应用@Autowired注解
@Autowired注解具有required属性
@Autowired注解也可以应用在数组类型的属性上
@Autowired注解也可以应用在集合属性上
@Autowired注解也可以用在java.util.Map上
2、Resource根据name值准确注入属性
@Component(value="userAction")
public class UserAction {
private UserService service;
@Autowired
public void setUserService(UserService service) {
this.service=service;
}
public void doPost(User user) {
System.out.println("action user:"+user.getName());
//调用业务层
service.login(user);
}
}
Aop面向切面过程:
1、是一种新的方法论,是对传统的面向对象编程的补充
2、编程时,仍然需要定义公共功能,但可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的对象里
AOP的好处:
1、每个事物逻辑位于一个位置,代码不分散,便于维护和升级
2、业务模块更简洁,只包含核心业务代码
使用动态代理解决问题:
使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上
切面:带有@Aspect注解的java类
通知:是标注有以下5种注解的简单的java方法
@Before:前置通知,在方法执行之前执行
@After:后置通知,在方法执行之后执行
@AfterRunning:返回通知,在方法返回结果之后执行
@AfterThrowing:异常通知,在方法抛出异常之后
@Around:环绕通知,围绕着方法执行
第一种方法:
<bean id="scoreLogger" class="com.jredu.aop.log.ScoreLogger"/>
<aop:config>
<aop:pointcut expression="execution(public int com.jredu.aop.service.ScoreService.*(int))" id="pointcut"/>
<aop:aspect ref="scoreLogger">
<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
<aop:after-returning method="afterMethod" pointcut-ref="pointcut" returning="result"/>
<aop:around method="arroundMethod" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
public class ScoreLogger {
public void beforeMethod(JoinPoint join){
String method=join.getSignature().getName();
int s=(int) join.getArgs()[0];
System.out.println("----方法调用之前-------调用的方法是:"+method+",方法执行前会员积分为:"+s);
}
public void afterMethod(JoinPoint join,Object result){
String method=join.getSignature().getName();
System.out.println("----方法调用之后-------调用的方法是:"+method+",方法执行后会员积分为:"+result);
}
public Object arroundMethod(ProceedingJoinPoint join) throws Throwable{
System.out.println("方法调用之前");
Object object=join.proceed();
System.out.println("方法调用之后");
return object;
}
}
@Component(value="score")
public class ScoreService {
public int register(int score){
return score+10;
}
public int addPhone(int score){
return score+10;
}
public int addId(int score){
return score+10;
}
public int winBid(int score){
return score+50;
}
public int deleteEmail(int score){
return score-10;
}
public int deletePhone(int score){
return score-10;
}
public int deleteMessage(int score){
return score-20;
}
}
第二种:
@Component(value="airth")
public class ArithmeticService {
public int add(int a,int b){
return a+b;
}
public int sub(int a,int b){
return a-b;
}
public int div(int a,int b){
return a/b;
}
public int mul(int a,int b){
return a*b;
}
}
@Aspect
public class ArithmeticLogger {
@Before("execution(public int com.jredu.aop.service.ArithmeticService.*(int,int))")
public void beforeMethod(JoinPoint join){
//打印调用的方法,打印方法运行前的情况
String method=join.getSignature().getName();//方法名字
int a=(Integer) join.getArgs()[0];
int b=(Integer) join.getArgs()[1];
System.out.println("----方法调用之前-------调用的方法是:"+method+",方法执行前是a="+a+",b="+b);
}
@After("execution(public int com.jredu.aop.service.ArithmeticService.*(int,int))")
public void afterMethod(JoinPoint join){
//打印调用的方法,打印方法运行后的情况
String method=join.getSignature().getName();//方法名字
System.out.println("----方法调用之后-------调用的方法是:"+method);
}
@AfterReturning(value="execution(public int com.jredu.aop.service.ArithmeticService.*(int,int))",returning="result")
public void afterreturning(JoinPoint join,Object result){
//打印调用的方法,打印方法运行后的情况
String method=join.getSignature().getName();//方法名字
System.out.println("----方法调用之后-------调用的方法是:"+method+"结果是"+result);
}
@Around(value="execution(public int com.jredu.aop.service.ArithmeticService.*(int,int))")
public Object arroundMethod(ProceedingJoinPoint join) throws Throwable{
System.out.println("方法调用之前");
Object object=join.proceed();
System.out.println("方法调用之后");
System.out.println("结果是"+object);
return object;
}
}
Spring中的事务管理器:
spring从不同的事务管理API中抽象了一整套的事务机制,开发人员不必了解地层的事务API,就可以利用这些事务机制。有了这些事务机制,事务管理代码就能独立于特定的事务技术了。
Spring的核心事务管理是PaltformTransactionManager,她为事务管理分装了一组独立于技术的方法。无论使用spring的哪种事务管理策略,事务管理器都是必须的。
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" p:driverClass="${jdbc.driverClassname}"
p:jdbcUrl="${jdbc.url}" p:user="${jdbc.user}" p:password="${jdbc.pwd}"
p:initialPoolSize ="${jdbc.initPoolSize}" p:maxPoolSize="${jdbc.maxPoolSize}"
/>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"
/>
<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 声明事务通知 -->
<tx:advice
id="bookServiceTxAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="buyBook" propagation="REQUIRES_NEW" isolation="READ_COMMITTED"/>
</tx:attributes>
</tx:advice>
<!-- aop面向切面配置 -->
<aop:config>
<!-- 切面接入点 -->
<aop:pointcut expression="execution(* com.jredu.book.service.BookService.*(..))"
id="bookOperation"/>
<!-- 根据切入点呼应的事务通知匹配 -->
<aop:advisor advice-ref="bookServiceTxAdvice"
pointcut-ref="bookOperation"/>
</aop:config>
@Service("bookService")
@Transactional
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Autowired
private UserDao userDao;
public String buyBook(String bookId, String userId,int count) {
// TODO Auto-generated method stub
Book book=bookDao.selectById(bookId);
User user=userDao.selectById(userId);
if(book.getAmount()<count) {
return "库存数量不足";
} else if(user.getMoney()<book.getPrice()*count) {
return "账户余额不足";
} else {
//购买图书
//账号扣款
user.setMoney(user.getMoney()-book.getPrice()*count);
int count1=userDao.update(user);
int count2=0;
//图书出库
int i=100/0;
if(count1>0) {
book.setAmount(book.getAmount()-count);
count2=bookDao.update(book);
}
if(count2>0) {
return "购买成功";
} else {
return "购买失败";
}
}
}
@Override
public String addBook(String bookId, int count) {
// TODO Auto-generated method stub
Book book=bookDao.selectById(bookId);
book.setAmount(book.getAmount()+count);
int count1=bookDao.add(book);
if(count1>0){
return "添加成功";
}else{
return "添加失败";
}
}
@Override
public String deleteBook(String bookId) {
// TODO Auto-generated method stub
int count1=bookDao.delete(bookId);
if(count1>0){
return "删除成功";
}else{
return "删除失败";
}
}
}