您的位置:首页 > 其它

框架源码学习笔记

2016-03-07 22:18 561 查看
1.@WebListener

Servlet3.0提供@WebListener注解将一个实现了特定监听器接口的类定义为监听器,这样我们在web应用中使用监听器时,也不再需要在web.xml文件中配置监听器的相关描述信息了。

Web应用启动时就会初始化这个监听器

@WebListener

public class MyServletContextListener implements ServletContextListener {

@Override

public void contextDestroyed(ServletContextEvent sce) {

System.out.println("ServletContex销毁");

}

@Override

public void contextInitialized(ServletContextEvent sce) {

System.out.println("ServletContex初始化");

System.out.println(sce.getServletContext().getServerInfo());

}

}

参考:Servlet3.0学习总结(四)——使用注解标注监听器(Listener)

2.ServletRegistration

只能在webapp启动在初始化时进行完成注册,可能是为了安全考虑吧.

在Servlet3.0中可以动态注册Servlet,Filter,Listener

servlet 3.0笔记之servlet的动态注册

第十六章_动态注册和Servlet容器初始化

3.setAccessible(true)

Method actionMethod

actionMethod.setAccessible(true); // 取消类型安全检测(可提高反射性能)

4.instanceof

instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。

java中instanceof用法

下面是调用Spring的函数

public class LogBeforeAdvice implements MethodBeforeAdvice {
private Logger logger=Logger.getLogger(this.getClass().getName());
public void before(Method method,Object[] args,Object target) throws Throwable{


注意:getClass返回的是Class类型



这里也可以用if(args[0].getClass().getName().contains("com.xxx"))来判断是否指定类,但是没用instanceof直观

5.判断Map是否为空

public static boolean isEmpty(Map map) {
return (map == null || map.isEmpty());
}


6.Map.Entry

// 初始化请求属性
Map<String, Object> data = view.getData();
if (MapUtil.isNotEmpty(data)) {
for (Map.Entry<String, Object> entry : data.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
}


视图操作 :处理映像中键/值对组

  Set keySet(): 返回映像中所有关键字的视图集

  “因为映射中键的集合必须是唯一的,您用Set支持。你还可以从视图中删除元素,同时,关键字和它相关的值将从源映像中被删除,但是你不能添加任何元素。”

  Collection values():返回映像中所有值的视图集

  “因为映射中值的集合不是唯一的,您用Collection支持。你还可以从视图中删除元素,同时,值和它的关键字将从源映像中被删除,但是你不能添加任何元素。”

  Set entrySet(): 返回Map.Entry对象的视图集,即映像中的关键字/值对

  “因为映射是唯一的,您用Set支持。你还可以从视图中删除元素,同时,这些元素将从源映像中被删除,但是你不能添加任何元素。”

  Map.Entry接口

  Map的entrySet()方法返回一个实现Map.Entry接口的对象集合。集合中每个对象都是底层Map中一个特定的键/值对。

  通过这个集合的迭代器,您可以获得每一个条目(唯一获取方式)的键或值并对值进行更改。当条目通过迭代器返回后,除非是迭代器自身的remove()方法或者迭代器返回的条目的setValue()方法,其余对源Map外部的修改都会导致此条目集变得无效,同时产生条目行为未定义。

  (1) Object getKey(): 返回条目的关键字

  (2) Object getValue(): 返回条目的值

  (3) Object setValue(Object value): 将相关映像中的值改为value,并且返回旧值

7.getRequestDispatcher()与sendRedirect()的区别

1.request.getRequestDispatcher()是请求转发,前后页面共享一个request ;

response.sendRedirect()是重新定向,前后页面不是一个request。

request.getRequestDispather();返回的是一个RequestDispatcher对象。

2.RequestDispatcher.forward()是在服务器端运行;

/**
* 转发请求
*/
public static void forwardRequest(String path, HttpServletRequest request, HttpServletResponse response) {
try {
request.getRequestDispatcher(path).forward(request, response);
} catch (Exception e) {
logger.error("转发请求出错!", e);
throw new RuntimeException(e);
}
}


8.引用JSTL

The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar
http://blog.csdn.net/lzz313/article/details/7554736 http://blog.sina.com.cn/s/blog_7ffb8dd501013fvl.html
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>


9.ThreadLocal

每个线程相互独立了,同样是 static 变量,对于不同的线程而言,它没有被共享,而是每个线程各一份,这样也就保证了线程安全。 也就是说,TheadLocal 为每一个线程提供了一个独立的副本!

public class SequenceB implements Sequence {

private static ThreadLocal<Integer> numberContainer = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};

public int getNumber() {
numberContainer.set(numberContainer.get() + 1);
return numberContainer.get();
}

public static void main(String[] args) {
Sequence sequence = new SequenceB();

ClientThread thread1 = new ClientThread(sequence);
ClientThread thread2 = new ClientThread(sequence);
ClientThread thread3 = new ClientThread(sequence);

thread1.start();
thread2.start();
thread3.start();
}
}


ThreadLocal 的 API,其实很简单

public void set(T value):将值放入线程局部变量中

public T get():从线程局部变量中获取值

public void remove():从线程局部变量中移除值(有助于 JVM 垃圾回收)

protected T initialValue():返回线程局部变量中的初始值(默认为 null)

为什么 initialValue() 方法是 protected 的呢?就是为了提醒程序员们,这个方法是要你们来实现的,请给这个线程局部变量一个初始值吧。

ThreadLocal 具体有哪些使用案例呢:通过 ThreadLocal 存放 JDBC Connection,以达到事务控制的能力。

当您在一个类中使用了 static 成员变量的时候,一定要多问问自己,这个 static 成员变量需要考虑“线程安全”吗?

也就是说,多个线程需要独享自己的 static 成员变量吗?如果需要考虑,那就请用 ThreadLocal 吧!

参考: ThreadLocal 那点事儿

10.return this

return this 返回的是当前方法所在的类的实例,例如 StringBuilder 中的 append,这样做的好处就是可以 append("XXX").append("XXX").append("XXX")....

public class ReturnThis
{
public int age;
public ReturnThis grow()
{
age++;
//return this,返回调用该方法的对象
return this;
}
public static void main(String[] args)
{
ReturnThis rt = new ReturnThis();
//可以连续调用同一个方法
rt.grow()
.grow()
.grow();
System.out.println("rt的age属性值是:" + rt.age);
}
}


这样连续调用同一个方法。

参考:初学Java,方法中返回this,连续调用方法(六)

java中的return this什么时候用

11.@SuppressWarnings注解

java.lang.SuppressWarnings是J2SE 5.0中标准的Annotation之一。可以标注在类、字段、方法、参数、构造方法,以及局部变量上。

作用:告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。

@SuppressWarnings("unchecked")

告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。

参考:http://blog.sina.com.cn/s/blog_ad8b5870010166vt.html

Java魔法堂:注解用法详解——@SuppressWarnings

例如:

@SuppressWarnings("unchecked")
public static <T> T getInstance(String cacheKey, Class<T> defaultImplClass) {


12.属性解析

/**
* 获取字符型属性
*/
public static String getString(Properties props, String key) {
String value = "";
if (props.containsKey(key)) {
value = props.getProperty(key);
}
return value;
}


13.抽象方法

1 用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法。例如 :

abstract class Animal { //用abstract来定义一个Animal为抽象类

}

public abstract void enjoy(); //用abstract来定义一个抽象方法"enjoy"

2 含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写。

3 抽象类不能被实例化。

4 抽象方法只需声明,而不需实现某些功能。

public abstract class ClassTemplate {
...
private void doAddClass(List<Class<?>> classList, String className) {
// 加载类
Class<?> cls = ClassUtil.loadClass(className, false);
// 判断是否可以添加类
if (checkAddClass(cls)) {
// 添加类
classList.add(cls);
}
}

/**
* 验证是否允许添加类
*/
public abstract boolean checkAddClass(Class<?> cls);
}


14.获取包名路径下的 class 文件或目录

// 获取包名路径下的 class 文件或目录
File[] files = new File(packagePath).listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});


15.内部类

参考:主题:【解惑】领略内部类的“内部”

内部类有两种情况:

(1) 在类中定义一个类(私有内部类,静态内部类)

(2) 在方法中定义一个类(局部内部类,匿名内部类)

对内部类进行编译后发现有两个class文件:Outer.class 和Outer$Inner.class 。

这说明内部类Inner仍然被编译成一个独立的类(Outer$Inner.class),而不是Outer类的某一个域。 虚拟机运行的时候,也是把Inner作为一种常规类来处理的。

编译器对类中内部类做的手脚吧:

(1) 在内部类中偷偷摸摸的创建了包可见构造器,从而使外部类获得了创建权限。

(2) 在外部类中偷偷摸摸的创建了访问私有变量的静态方法,从而 使 内部类获得了访问权限。

这样,类中定义的内部类无论私有,公有,静态都可以被包围它的外部类所访问。

方法内部类也有两个特点

(1) 方法中的内部类没有访问修饰符, 即方法内部类对包围它的方法之外的任何东西都不可见。

(2) 方法内部类只能够访问该方法中的局部变量,所以也叫局部内部类。而且这些局部变量一定要是final修饰的常量。

内部类的特点总结

(1) 在方法间定义的非静态内部类:

● 外围类和内部类可互相访问自己的私有成员。

● 内部类中不能定义静态成员变量。

(2) 在方法间定义的静态内部类:

● 只能访问外部类的静态成员。

(3) 在方法中定义的局部内部类:

● 该内部类没有任何的访问控制权限

● 外围类看不见方法中的局部内部类的,但是局部内部类可以访问外围类的任何成员。

● 方法体中可以访问局部内部类,但是访问语句必须在定义局部内部类之后。

● 局部内部类只能访问方法体中的常量,即用final修饰的成员。

(4) 在方法中定义的匿名内部类:

● 没有构造器,取而代之的是将构造器参数传递给超类构造器。

private void addClass(List<Class<?>> classList, String packagePath, String packageName) {
try {
// 获取包名路径下的 class 文件或目录 File[] files = new File(packagePath).listFiles(new FileFilter() { @Override public boolean accept(File file) { return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory(); } });


16.匿名内部类

抽象类

abstract class Person {
public abstract void eat();
}
实现类

public class Child extends Person{
public void eat() {
System.out.println("eat something");
}
}


调用比较

//正常调用
Person p = new Child();
p.eat();

//匿名内部类
Person p2 = new Person(){
public void eat() {
System.out.println("eat something");
}
};


输出都是一样的

参考:java中的匿名内部类总结

java中匿名内部类的两种实现方式

匿名内部类的两种实现方式:

第一种,继承一个类,重写其方法;第二种,实现一个接口(可以是多个),实现其方法。

匿名内部类有了自己的实现。

使用匿名内部类是因为我这地方需要有点什么特殊的实现,所以我就在这地方把具体实现也给了出来了,然后我就在这地方获取它的实例,调用它的方法。

匿名内部类就是重写父类或接口的方法。

匿名内部类是没有名字的,所以我们没办法获得其类型,而只能把它当作超类或接口类型来使用。

17.final关键字

final这个关键字的含义是“这是无法改变的”或者“终态的”;

那么为什么要阻止改变呢?

java语言的发明者可能由于两个目的而阻止改变:

1).效率问题:

jdk中的某些类的某些方法,是不允许被用户覆盖的,设计者可能认为,所用方法已经是最好的方法,

用户私自覆盖,或是由于疏忽而覆盖,就会影响JVM或是系统的系能;

2). 设计所需:

众所周知,有些情况必须使用final关键字,比如方法中的匿名内部类的参数传递;

【final关键字的使用方法】:

【修饰变量】:

final成员变量表示常量,只能被赋值一次,赋值后值不再改变。

【修饰方法】:

final方法不能被子类方法覆盖,但可以被继承。

【修饰类】:

final类不能被继承,没有子类,final类中所有方法都是final的。

比如util类

public final class FileUtil {

private static final Logger LOGGER = LoggerFactory.getLogger(FileUtil.class);

/**
* 获取真实文件名(自动去掉文件路径)
*/
public static String getRealFileName(String fileName) {
return FilenameUtils.getName(fileName);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: