参考链接:http://www.bubuko.com/infodetail-690646.html
在上面的代码中,循环申请object对象,并添加到Vector中,然后设置object=null(就是清除栈中引用变量object),但是这些对象被vector引用着,必然不能被GC回收,造成内存泄露。因此要释放这些对象,还需要将它们从vector中删除,最简单的方法就是将vector=null,清空集合类中的引用。
- 注意:对于物理连接,一般把这些代码放在spring容器中,避免内存泄露。
匿名内部类是什么?
如何访问在其外面定义的变量?
当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
Servlet接口定义了5个方法,其中前三个方法与servlet生命周期有关:
Web容器加载servlet并将其实例化后,servlet生命周期开始,容器运行其init()方法进行servlet的初始化;请求到达时调用servlet的service()方法,service()方法会根据需要调用与请求对应的doGet或doPost等方法;当服务器关闭或项目被卸载时,服务器会将servlet实例销毁,此时会调用servlet的destroy()方法。
Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。
由于http协议本身是无状态的,服务器为了区分不同的用户,就需要对用户会话进行跟踪,简单的说就是为用户进行登记,为用户分配唯一的id,下一次用户在请求中包含此id,服务器据此判断到底是哪一个用户。
这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改url或则在页面中添加隐式表单域来存储用户会话相关信息,事情将变得非常麻烦。
补充:html5中可以使用web storage技术通过javaScript来保存数据,例如可以使用localStorage和sessionStroage来保存用户会话的信息,也能够实现会话跟踪。
加载顺序context-param -> listener -> filter -> servlet
可参考链接:http://blog.csdn.net/lovesummerforever/article/details/46859705 和百度面经
(1)tomcat加载应用程序都是从读web.xml文件开始的。读web.xml的核心就是从读节点开始listener>filter>servlet.其实还有一个这个标签是提供应用程序上下文信息(可以写在任意位置)。因此加载的顺序是:context-param—->listener—->filter—–>servlet.
(2)各个标签的简单说明
1)context-param加载上下文的配置文件(主要是java bean)
2)listener监听器
通过监听器的通配符,将配置信息加载到spring容器中.还有一般事务写在spring(业务逻辑层),事务的启动也是靠listener.
3)filter过滤器
Struts就是依靠过滤器来实现action的访问。
4)servlet是我们的后台程序java类。
1.Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。
Struts 2
Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何有execute标识的POJO对象(就是简单的javabean)都可以用作Struts2的Action对象。
博文:
http://www.cnblogs.com/ITtangtang/p/3978349.html
http://www.ithao123.cn/content-9827758.html (可以看看获得各种容器的实现)
- (1)创建IOC配置文件的抽象资源;
- (2)创建一个BeanFactory;
- (3)把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory;
- (4)从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReade来完成,这样完成整个载入bean定义的过程;
传统创建对象的缺陷:
传统创建对象,通过关键字new获得。但是如果在不同的地方创建很多相同的对象,不仅占用很大的内存,同时影响性能。
改进的思路:
仿造工厂模式,需要什么对象,直接拿过来,按照用户需求,组装相应的产品。以后不再通过new获取对象,而是需要什么对象,就在spring容器中取就行了。这就是将创建对象这个行为,进行控制反转,交由容器去完成。什么时候需要这些对象,再通过依赖注入的方式去获取这些对象。
1、注解方式注入
xml version="1.0" encoding="UTF-8"?>
"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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
"org.zttc.itat.spring"/>
// 等价于
//公共创建bean的annototion
@Component("userDAO")
// 一般用于DAO的注入,Spring3新增注解方式
@Repository("userDAO")
@Scope("prototype")
public class UserDAO implements IUserDAO {
......
}
@Component("userService")
//@Service一般用于业务层
@Service("userService")
public class UserService implements IUserService {
private IUserDAO userDAO;
public IUserDAO getUserDAO() {
return userDAO;
}
// 默认通过名称进行注入,在JSR330中提供了@Inject来进行注入,需导入相应的包
@Resource
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
......
}
@Component("userAction")
//MVC的控制层一般使用@Controller
@Controller("userAction")
@Scope("prototype")
public class UserAction extends ActionSupport {
......
}
注:项目较大时,按照模块进行划分,模块中再按层划分,而非按层(MVC)进行划分;中小型项目按层划分。
2、Setter方法注入
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="org.zttc.itat.spring.model.HelloWorld" scope="prototype"/>
<bean id="user" class="org.zttc.itat.spring.model.User">
<property name="id" value="2"/>
<property name="username" value="八戒"/>
bean>
<bean id="userDao" class="org.zttc.itat.spring.dao.UserDao">bean>
<bean id="userJDBCDao" class="org.zttc.itat.spring.dao.UserJDBCDao">bean>
<bean id="userService" class="org.zttc.itat.spring.service.UserService">
<property name="userDao" ref="userDao">property>
bean>
<bean id="userAction" class="org.zttc.itat.spring.action.UserAction" scope="prototype">
<property name="userService" ref="userService"/>
<property name="user" ref="user"/>
<property name="id" value="12"/>
<property name="names">
<list>
<value>aaavalue>
<value>bbbvalue>
<value>cccvalue>
list>
property>
bean>
beans>
public class UserAction{
private UserService userService;
public String login(){
userService.valifyUser(xxx);
}
public void setUserService(UserService userService){
this.userService = userService;
}
}
3、构造方法注入
public class UserAction{
private final UserService userService;
public String login(){
userService.valifyUser(xxx);
}
public UserAction(UserService userService){
this.userService = userService;
}
}
三种注入方式对比
注解方式注入:
Setter 注入:
构造器注入:
传统事务、日志编写的缺陷
很多项目上,在相应的业务上需要事务和日志的管理,许多业务上的事务、日志代码又都是一样的,这样造成了代码上的重复;
改进的思路:
让这些重复的代码抽取出来,让专门的一个类进行管理。
AOP的实现:
在需要的地方加上通知(可以在目标代码前后执行),将相同的业务交由代理类去执行(比如日志、事务),然后再执行目标类,实现了代码的复用。
静态代理的缺陷:
相同的业务交由代理类去处理,那么需要日志管理,就要创建一个日志代理类,需要事务管理,就要创建事务代理类……,这样会造成代理类的无限膨胀。
改进的措施:
根据这些类,来动态的创建代理类。所以在这个过程,要实现两个步骤:
package org.zttc.itat.spring.proxy;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component(“logAspect”)//让这个切面类被Spring所管理
@Aspect//申明这个类是一个切面类
public class LogAspect {
/**
* execution(* org.zttc.itat.spring.dao..add(..))
* 第一个*表示任意返回值
* 第二个*表示 org.zttc.itat.spring.dao包中的所有类
* 第三个*表示以add开头的所有方法
* (..)表示任意参数
*/
@Before(“execution(* org.zttc.itat.spring.dao..add(..))||” +
“execution(* org.zttc.itat.spring.dao..delete(..))||” +
“execution(* org.zttc.itat.spring.dao..update(..))”)
public void logStart(JoinPoint jp) {
//得到执行的对象
System.out.println(jp.getTarget());
//得到执行的方法
System.out.println(jp.getSignature().getName());
Logger.info(“加入日志”);
}
/**
* 函数调用完成之后执行
* @param jp
*/
@After(“execution(* org.zttc.itat.spring.dao..add(..))||” +
“execution(* org.zttc.itat.spring.dao..delete(..))||” +
“execution(* org.zttc.itat.spring.dao..update(..))”)
public void logEnd(JoinPoint jp) {
Logger.info(“方法调用结束加入日志”);
}
/**
* 函数调用中执行
* @param pjp
* @throws Throwable
*/
@Around(“execution(* org.zttc.itat.spring.dao..add(..))||” +
“execution(* org.zttc.itat.spring.dao..delete(..))||” +
“execution(* org.zttc.itat.spring.dao..update(..))”)
public void logAround(ProceedingJoinPoint pjp) throws Throwable {
Logger.info(“开始在Around中加入日志”);
pjp.proceed();//执行程序
Logger.info(“结束Around”);
}
}
动态代理主要实现了两个东西
实现
Proxy.newProxyInstance(ClassLoad loader, Class[] interfaces,InvocationHandler h)
// 我们要代理的真实对象
RealSubject rs = new RealSubject();
// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
InvocationHandler invocationHandler = new DynamicSubject(rs);
Class cl = rs.getClass();
Subject subject = (Subject) Proxy.newProxyInstance(cl.getClassLoader(), cl.getInterfaces(), invocationHandler);
// 代理对象执行方法
subject.request();
动态代理实现步骤
1、jdk动态代理
2、CGlIb动态代理(通过继承实现)
4、并用Session对象生成Transaction对象;
A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作;
B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中。
(1)hibernate的session提供了一级缓存的功能,默认总是有效的,当应用程序保持持久化实体,修改持久化实体时,session并不会立即把这种改变提交到数据库,而是缓存在当前的session中,除非显示调用了session的flush()方法或通过close()方法关闭session。通过一级缓存,可以减少程序与数据库的交互,从而提高数据库访问的性能。
(2)sessionFactory级别的二级缓存是全局性的,所有的session可以共享这个二级缓存。不过二级缓存默认是关闭的,需要显示开启并指定需要使用哪种二级缓存实现类(可以使用第三方提供的实现)。一旦开启了二级缓存并设置了需要使用二级缓存的实体类,sessionFactory就会缓存访问过的该实体类的每个对象,除非缓存的数据超出了指定的缓存空间。
get和load方法是根据id去获得对应数据
1、translent(瞬时态)
实体对象在内存中的存在,与数据库中的记录无关,通过session的save()或saveOrUpdate()方法变成持久态;
2、Persisent(持久态)
该状态下的实体对象与数据库中的数据保持一致;
3、Detached(托管状态)
操作托管态的数据不能影响到数据库的修改;
Springmvc的工作流程:(面试的时候一定会画Springmvc的运行图,结合图讲比较好)
Mybatis优势:
Hibernate优势: