黑马程序员_类加载器

 

-------------------------------------------------android培训java培训期待与您交流!----------------------------------

一、概述

1.java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap(JRE/lib/rt.jar)、ExtClassLoader(JRE/lib/ext/*.jar)、AppClassLoader(ClassPath指定的所有jar或目录)

2.类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须第一个类加载器不是不是java类,这正是BootStrap

3.Java虚拟机的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指一个父级装载器对象或者默认采用系统类装载器为其父级类加载

4.当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?

1)首先当前线程的类加载器去加载线程的第一个类

2)如果类A中引用了类B,Java虚拟机将使用加为A的类装载器来加载类B

3)还可以直接调用ClassLoder.loadClass()方法来指定某个类加载器去加载某个类

5.每个类加载器加载类时,又先委托给其上级类加载器

当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个?

二、类的加载过程

public class SingerClass

{

    private static SingerClass singer=new SingerClass();

    public static int count1;

    public static int count2=0;

    private SingerClass()

    {

        System.out.println("加载中……");

        count1++;

        count2++;

    }

    public static SingerClass newInstence()

    {

        return singer;

    }

}

public class SingerTest

{

    public static void main(String[] args)

    {

        SingerClass singer=SingerClass.newInstence();

        System.out.println(SingerClass.count1);//1

        System.out.println(SingerClass.count2);//0 why?

       

        //for

        //(1)类的主动使用,会加载类

        /*

         * 1.创建类的实例

         * 2.访问某个类或接口的静态变量,或者对该静态变量赋值

         * 3.调用类的静态方法

         * 4.反射(Class.forName("com.sun.test")

         * 5.初始化一个类的子类

         * 6.Java虚拟机启动时被标明为启动的类

         */

        //(2)类的执行

        /*

         * 1.类加载器来加载,加载到方法区

         * 2.检查类的文件的正确性

         * 3.类静态字段的默认初始

         * 4.类静态字段的正确默认(用户赋的值)

         * 5.在堆中生成对应Class对象

         */

    }

}

//相关final加载

public class FinalTest1

{

    public static void main(String[] args)

    {

        System.out.println(Final1.x);

        //System.out.println(Final1.b);

        //System.out.println(Final1.c);

        //总之:调用的如不确定,就要初始块

    }

}

class Final1

{

    public static int a=12;

    public static final int x=2;

    public static final int b;

    public static final int c=new Random().nextInt(100);

    //下面不会被执行,因为是final类型,那么它的值2就确定了

    //但外部调用b,不确定就执行

    static

    {

        b=1;

        System.out.println("我执行了!");

    }

}

三、自定义类加载

//自定义类加载器继承ClassLoader类

public class UserLoader extends ClassLoader

{

    private String name;

    private String path="D:\\";

   

    private String className=".class";

   

    public UserLoader(String name)

    {

        super();

        this.name=name;

    }

    public UserLoader(ClassLoader classLoader,String name)

    {

        super(classLoader);

        this.name=name;

    }

   

    public String getPath()

    {

        return path;

    }

    public void setPath(String path)

    {

        this.path = path;

    }

//先执执行loadClass方法,首先找系统加载器,如果不能加载就找根加载器,再不能就使用findClass找到的Class,最后不能就报错

    @Override

    protected Class<?> findClass(String name) throws ClassNotFoundException

    {

        byte[] b=loadClassData(name);

        return defineClass(name, b, 0, b.length);

    }

    //转换为字节

    private byte[] loadClassData(String name)

    {

        byte[] b=null;

        InputStream in=null;

        ByteArrayOutputStream baos=new ByteArrayOutputStream();

        try

        {

            name=name.replace(".", "\\");

            in=new FileInputStream(new File(path+name+className));

            int len=0;

            while(-1!=(len=in.read()))

            {

                baos.write(len);

            }

            b=baos.toByteArray();

        }

        catch (Exception e)

        {

            e.printStackTrace();

        }

        finally

        {

           

            try

            {

                in.close();

                baos.close();

            }

            catch (Exception e)

            {

                e.printStackTrace();

            }

        }

        return b;

    }

    @Override

    public String toString()

    {

        return this.name;

    }

    public static void main(String[] args)

    {

        UserLoader ul=new UserLoader("ul");

        ul.setPath("E:\\ClassPath\\");

        //指定ul作为父类加载器,如果ul加载不了就交给了系统加载器

        UserLoader ul1=new UserLoader(ul, "ul1");

        ul1.setPath("E:\\Class\\");

        try

        {

            //本类由系统加载器加载,ClassTest由用户加载器加载                           Class<?> testClass=ul1.loadClass("ClassTest");

            Object o=testClass.newInstance();

            //ClassTest test=(ClassTest)o;

            ul=null;//类的加载器卸载(只有用户加载器可以)

//但Class还是可以用的

            Field[] fields=testClass.getFields();

            System.out.println(fields[0].getInt(o));

        }

        catch (Exception e)

        {

            e.printStackTrace();

        }

    }

}

 

-------------------------------------------------android培训java培训期待与您交流!----------------------------------

详细请查看:http://edu.youkuaiyun.com/heima

### JavaWeb 过滤器详解 #### 过滤器的概念与作用 过滤器(Filter)是在Servlet技术中实现的一种拦截机制,用于在请求到达Servlet之前处理客户端发送的数据。通过定义一系列的过滤规则,可以在请求被处理前或响应返回客户机之前执行特定的操作。 #### 过滤器的工作流程 当Web容器启动后会依据`web.xml`配置文件来创建并初始化过滤器对象[^2]。具体来说: - **实例化**:每当服务器重启时都会重新加载应用程序,并按照部署描述符中的声明顺序依次创建各个过滤器类的对象。 - **初始化 (`init()` 方法)**:一旦完成上述操作,则立即调用该方法来进行必要的准备工作;此时还可以访问来自`<filter>`标签下的参数设置以便于自定义行为逻辑。 ```java @Override public void init(FilterConfig filterConfig) throws ServletException { String paramValue = filterConfig.getInitParameter("paramName"); System.out.println("Initialization parameter value is " + paramValue); } ``` - **核心业务逻辑(`doFilter()` 方法)** :这是最为重要的部分之一,它决定了如何以及何时继续传递控制权给链路下游组件或是终止当前事务流。此过程中允许开发者插入任意数量中间件服务以增强应用功能特性。 ```java @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { // Pre-processing logic here chain.doFilter(request,response); // Passes the request/response along to next element in chain. // Post-processing logic here (if needed) } ``` - **销毁 (`destroy()` 方法)** : 当不再需要某个过滤器实例时会被自动回收内存空间,通常在此处清理静态变量或其他外部依赖关系。 --- #### 配置过滤器 为了使过滤器生效,必须将其注册到项目的部署描述符 `WEB-INF/web.xml` 文件内,如下所示: ```xml <!-- Define a new filter --> <filter> <filter-name>MyCustomFilter</filter-name> <filter-class>mypackage.MyCustomFilter</filter-class> <!-- Optional initialization parameters can be added below --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <!-- Map this filter to specific URL patterns or servlet names --> <filter-mapping> <filter-name>MyCustomFilter</filter-name> <url-pattern>/secure/*</url-pattern> </filter-mapping> ``` 也可以采用基于注解的方式简化配置过程,只需简单地添加相应的元数据即可让框架自动识别和管理这些组件。 ```java @WebServlet("/example") @javax.servlet.annotation.WebFilter(urlPatterns={"/secure/*"}) public class MyCustomFilter implements javax.servlet.Filter { ... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值