一、用分层思想实现程序结构优化
(1)这是一个基于SSH框架的网站文件布局
(2)以下是一个基于SSH框架的网站流程图
(3)以下是一个基于SSM框架的网站流程图
二、Spring IOC功能详述
1.注解方式实现IOC
使用注解方式之前,在applicationContext.xml里面加上一下配置:
<!-- 自动装配 -->
<context:annotation-config/>
<!-- 指定组件的路径 -->
<context:component-scan base-package="com.juligang.dao.impl,com.juligang.service.impl,com.juligang.action.UserAction"></context:component-scan>
Action层
package com.juligang.action;
import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.juligang.model.User;
import com.juligang.service.UserService;
public class UserAction {
User user;
UserService service; //调用Service层
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public UserService getService() {
return service;
}
@Resource(name="service") //通过注解方式注入service
public void setService(UserService service) {
this.service = service;
}
public String addOrUpdate()
{
service.add(user);
return login();
}
public String checkExist()
{
user=service.check(user);
HttpServletResponse response=ServletActionContext.getResponse();
try {
PrintWriter out=response.getWriter();
if(null!=user)
{
out.print("YES!"+user.getId());
}
else
{
out.print("NO!"+user.getId());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public String login()
{
//context只在一次请求时有效
//ActionContext context=ActionContext.getContext();
//context.put("USER", user);
HttpServletRequest request=ServletActionContext.getRequest();
HttpSession session=request.getSession();
session.setAttribute("USER", user);
return "main";
}
public String exit()
{
HttpServletRequest request=ServletActionContext.getRequest();
HttpSession session=request.getSession();
session.setAttribute("USER", null);
return "main";
}
}
Service实现层
package com.juligang.service.impl;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import com.juligang.dao.UserDAO;
import com.juligang.model.User;
import com.juligang.service.UserService;
@Component(value="service") //通过注解建立一个service实现类,共Action层装配
public class UserServiceImpl implements UserService {
UserDAO dao;
// 这是构造函数方式注入
// public UserServiceImpl(UserDAO dao) {
// super();
// this.dao = dao;
// }
// 这是setter方式注入
public UserDAO getDao() {
return dao;
}
@Resource(name="sqlDAO") //通过注解给DAO装配一个实现类
//可以装配sqlDAO,也可装配fileDAO
public void setDao(UserDAO dao) {
this.dao = dao;
}
@Override
public void add(User user) {
// TODO Auto-generated method stub
dao.save(user);
}
@Override
public User check(User user) {
// TODO Auto-generated method stub
return dao.check(user);
}
}
DAO实现层
(1)MySQL实现层
package com.juligang.dao.impl;
import javax.annotation.Resource;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.stereotype.Component;
import com.juligang.dao.UserDAO;
import com.juligang.model.User;
@Component(value="sqlDAO") //DAO实现类1
public class UserDAOMySqlImpl implements UserDAO {
HibernateTemplate hibernateTemplate;
@Resource
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
@Override
public void save(User user) {
hibernateTemplate.merge(user);
}
@Override
public User check(User user) {
// TODO Auto-generated method stub
return hibernateTemplate.findByExample(user).get(0);
}
}
(2)File实现类
package com.juligang.dao.impl;
import java.io.FileWriter;
import java.io.IOException;
import org.springframework.stereotype.Component;
import com.juligang.dao.UserDAO;
import com.juligang.model.User;
@Component(value="fileDAO") //DAO实现类2
public class UserDAOFileImpl implements UserDAO {
@Override
public void save(User user) {
// TODO Auto-generated method stub
FileWriter fw;
try {
fw = new FileWriter("e:\\Users.txt",true);
fw.write(user.getName()+":"+user.getPwd());
fw.write("\r\n");
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public User check(User user) {
// TODO Auto-generated method stub
return user;
}
}
注解方式总结:
Action层
@Resource(name=”userService”) //装配对象
Service实现层
@Component(value=”userService”) //初始化一个对象
@Resource(name=”sqlDAO”)
DAO实现层
@Component(value=”sqlDAO”)
@Component(value=”fileDAO”)
注意:如果把Component里面的value和Resource里面的name省略掉,那么默认值为类的第一个字母小写全称
这也是基于分层思想的技术实现
2.XML方式实现IOC
与注解方式实现的效果一样,只是把装配控制权交给了XML配置文件
IoC=控制反转=inverse of control
注解方式控制权在源代码中,通过这种方式,控制权在配置文件中
DI =依赖注入=dependency injection
同样是上面的程序
去掉@Component和@Resource注解,这些定义和装配的任务都放在.xml文件中
<!-- UserDAOFileImpl类实例一个对象filedao,以下类似 -->
<bean id="fileDAO" class="com.juligang.dao.impl.UserDAOFileImpl"></bean>
<bean id="sqlDAO" class="com.juligang.dao.impl.UserDAOMySqlImpl"></bean>
<!-- service是Action中的属性,依赖于dao的注入 -->
<bean id="service" class="com.juligang.service.impl.UserServiceImpl">
<!-- dao是service实现类中的属性,依赖于dao的实现类注入 -->
<property name="dao" ref="sqlDAO"></property>
</bean>
不能像注解方式那样一层一层往上装配。
3.Spring IoC的基本原理
inverse of control = 控制反转
dependency injection = 依赖注入
帮我们创建对象,帮我们组织和装配对象
1.自动装配
autowire :byName,byType
(1)默认的装配方式
<bean id="fileDAO" class="com.juligang.dao.impl.UserDAOFileImpl"></bean>
<bean id="sqlDAO" class="com.juligang.dao.impl.UserDAOMySqlImpl"></bean>
<bean id="service" class="com.juligang.service.impl.UserServiceImpl">
<property name="dao" ref="sqlDAO"></property>
</bean>
(2)自动装配autowire :byName
<bean id="dao" class="com.juligang.dao.impl.UserDAOFileImpl"></bean>
<bean id="service" class="com.juligang.service.impl.UserServiceImpl" autowire="byName">
</bean>
UserServiceImpl类中有一个属性dao,需要注入,我们设置autowire=”byName”,所以Spring会自动去寻找跟dao名字相同的实现进行装配
由于dao有2个实现类,你要装配哪个,就把那个实例成dao
(3)自动装配autowire :byType
<bean id="fileDAO" class="com.juligang.dao.impl.UserDAOFileImpl"></bean>
<bean id="sqlDAO" class="com.juligang.dao.impl.UserDAOMySqlImpl"></bean>
<bean id="service" class="com.juligang.service.impl.UserServiceImpl autowire="byType"">
</bean>
由于dao的实现类有两个,如果根据Type去自动装配会出问题,如果只有一个实现类,那么与根据Name装配效果一样
default-autowire:byname,byType
它是beans的一个属性,bean的属性autowire类似,不再举例
public class UserServiceImpl implements UserService {
UserDAO dao;
// 这是构造函数方式注入
// public UserServiceImpl(UserDAO dao) {
// super();
// this.dao = dao;
// }
// 这是setter方式注入
public UserDAO getDao() {
return dao;
}
@Resource(name="sqlDAO")
public void setDao(UserDAO dao) {
this.dao = dao;
}
被注释的代码采用的就是构造函数方式注入的,不过xml文件的配置也不同,如下:
<bean id="fileDAO" class="com.juligang.dao.impl.UserDAOFileImpl"></bean>
<bean id="sqlDAO" class="com.juligang.dao.impl.UserDAOMySqlImpl"></bean>
<bean id="service" class="com.juligang.service.impl.UserServiceImpl">
<constructor-arg name="dao" ref="sqlDAO"></constructor-arg >
</bean>
3.不同属性的注入方式,只做了解
简单属性注入:int,String,float
集合属性注入:Map,List,Set
4.bean的单实例与多实例属性
scope = singleton,prototype,request,session,global session
默认是singleton 单例,prototype 原型,模板
比较两个类的区别
class Student
{
private int age;
public void setAge(int age)
{
this.age=age;
}
public void show()
{
System.out.println(age);
}
}
class StudentDAO
{
public void save(Student student)
{
......
}
}
Student zhang=new Student();
zhang.setAge(20);
Student lee=new Student();
lee.setAge(18);
这种有参的类,不能是单实例,否则每个实例都一样,会有问题。
5.延时加载
lazy-init 容器加载时不初始化
default-lazy-init
6.初始化方法和销毁方法
init-method 和 destroy-method
在类中写一个初始化方法和一个销毁方法,在bean的属性中加以说明,如果方法初始化或完成时会被调用到。
三、Spring AOP功能详述
- AOP基本原理及面向切面编程的实现
复习动态代理,
作用:可以在现有方法之上添加代码,增加现有程序的功能。
讲好处!
1.将与业务无关的通用功能抽取出来,单独编写,
开发人员可以专注于业务逻辑的编写。
这些通用功能包括日志,权限管理,事务处理,异常处理等。
2.通用功能的增加与删除,可以通过配置文件进行配置。
3.是一种编程方式的革命!
引入AOP:面向切面的编程
AOP=面向切面编程=Aspect Oriented Programming
技术原理:动态代理
之前讲过的OOP
OOP=面向对象编程=Object Oriented Programming
AOP 类似jsp中的filter(过滤器),struts2中的interceptor(拦截器)
注解配置,XML配置
(1)学习在注解方式使用aop
这个功能应该加在哪个类的哪个方法上??是加在方法执行之前,还是之后??
@Before(“execution(public void net.xinqushi.service.impl.save(net.xinqushi.model.User))”)
spring中使用了一套面向aop编程的框架,叫做aspectj。
修改spring配置文件applicationContext.xml
添加AOP的命名空间及xml约束文件
xmlns:aop=”http://www.springframework.org/schema/aop”
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
增加支持注解功能
AOP详解及通过XML配置实现的方法
Spring AOP 的一些术语切面(Aspect)
要增加什么功能?事务管理,日志管理,权限管理,异常处理连接点(Joinpoint)
哪个类的哪个方法上增加功能?通知(Advice)
加在方法的什么位置?前面?后面?产生异常时?环绕??切入点(Pointcut)
给连接点命名,便于在多处使用。目标对象(Target Object)
被代理对象,自己的功能不够强大,要通过aop加强。AOP代理(AOP Proxy)
功能已经加强的哪个对象织入(Weaving)
把新功能和本身的功能组织在一起执行。
1.joinpoint语法:用一些通配符来定义在哪些类和方法上增加aop功能。
语法:
1).execution(public * *(..))
所有public方法
2).execution(* set*(..))
所有以set作为方法名开头的方法
3).exuection(* com.xzy.service.AccountService.*(..))
com.xzy.service.AccountService类中的所有方法
4).execution(* com.xyz.service..(..))
com.xyz.service包中所有类的所有方法
5).execution(* com.xyz.service...(..))
com.xyz.service包及子包下的所有类的所有方法
2.pointcut:给joinpoint取个名字。
@pointcut(“execution( * com.xzy..(..))”)
public void businessService(){}
3.advice
@Before
@AfterReturning
@AfterThrowing
@After(finally)
@Around
4.JoinPoint jp
ProceedingJointPoint pjp
定义了Pointcut之后,很多方法都可以添加此切面,无法区分。所以可以给方法传入参数,切面执行时可以带上方法本身特有的属性加以与其他方法区分。
5.xml配置AOP
<bean id="log" class="com.juligang.aop.Log"></bean> //初始化一个切面对象
<aop:config>
<aop:aspect ref="log"> //装配一个切面
<aop:pointcut //定义切入点
expression="execution(* net.xinqushi.dao.impl.*.*(..))" id="pt"/>
<aop:before method="before" pointcut-ref="pt"/>
<aop:after method="after" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>