javassist庫小實例的簡單介紹

本文目錄一覽:

使用JAVASSIST怎樣向Class文件中加入import語句?

在ECLIPSE下打開我這個JAVASSIST工程的屬性對話框,選擇Java Build Path – Library,把將要用到的庫導入進去,JAVASSIST就能找到了

struts2.2 jar包里為什麼沒有javassist.jar包

這個包是 struts2.2.1開始才依賴的,可能開發組沒來得及加進下載包里吧!之前版本的struts是不需要這個包的,不知道你用不用maven,用的話只要寫依賴就行了,maven會自動去它的倉庫下載的,不過還是給倉庫的地址你好了,呵呵

需要哪個版本就選哪個吧

springmnv框架怎麼搭建

一、Spring MNV環境搭建:

1. jar包引入

Spring 2.5.6:spring.jar、spring-webmvc.jar、commons-logging.jar、cglib-nodep-2.1_3.jar

Hibernate 3.6.8:hibernate3.jar、hibernate-jpa-2.0-api-1.0.1.Final.jar、antlr-2.7.6.jar、commons-collections-3.1、dom4j-1.6.1.jar、javassist-3.12.0.GA.jar、jta-1.1.jar、slf4j-api-1.6.1.jar、slf4j-nop-1.6.4.jar、相應數據庫的驅動jar包

2. web.xml配置(部分)

!– Spring MVC配置 —

!– ====================================== —

servlet

servlet-namespring/servlet-name

servlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class

!– 可以自定義servlet.xml配置文件的位置和名稱,默認為WEB-INF目錄下,名稱為[servlet-name]-servlet.xml,如spring-servlet.xml

init-param

param-namecontextConfigLocation/param-name

param-value/WEB-INF/spring-servlet.xml/param-value 默認

/init-param

load-on-startup1/load-on-startup

/servlet

servlet-mapping

servlet-namespring/servlet-name

url-pattern*.do/url-pattern

/servlet-mapping

!– Spring配置 —

!– ====================================== —

listener

listener-classorg.springframework.web.context.ContextLoaderListener/listener-class

/listener

!– 指定Spring Bean的配置文件所在目錄。默認配置在WEB-INF目錄下 —

context-param

param-namecontextConfigLocation/param-name

param-valueclasspath:config/applicationContext.xml/param-value

/context-param

3. spring-servlet.xml配置

spring-servlet這個名字是因為上面web.xml中servlet-name標籤配的值為spring(servlet-namespring/servlet-name),再加上「-servlet」後綴而形成的spring-servlet.xml文件名,如果改為springMVC,對應的文件名則為springMVC-servlet.xml。

?xml version=”1.0″ encoding=”UTF-8″?

beans xmlns=””

xmlns:xsi=”” xmlns:p=””

xmlns:context=””

xsi:schemaLocation=”

!– 啟用spring mvc 註解 —

context:annotation-config /

!– 設置使用註解的類所在的jar包 —

context:component-scan base-package=”controller”/context:component-scan

!– 完成請求和註解POJO的映射 —

bean class=”org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter” /

!– 對轉向頁面的路徑解析。prefix:前綴, suffix:後綴 —

bean class=”org.springframework.web.servlet.view.InternalResourceViewResolver” p:prefix=”/jsp/” p:suffix=”.jsp” /

/beans

4. applicationContext.xml配置

?xml version=”1.0″ encoding=”UTF-8″?

beans xmlns=””

xmlns:xsi=””

xmlns:aop=””

xmlns:tx=””

xsi:schemaLocation=”

!– 採用hibernate.cfg.xml方式配置數據源 —

bean id=”sessionFactory” class=”org.springframework.orm.hibernate3.LocalSessionFactoryBean”

property name=”configLocation”

valueclasspath:config/hibernate.cfg.xml/value

/property

/bean

!– 將事務與Hibernate關聯 —

bean id=”transactionManager” class=”org.springframework.orm.hibernate3.HibernateTransactionManager”

property name=”sessionFactory”

ref local=”sessionFactory”/

/property

/bean

!– 事務(註解 )–

tx:annotation-driven transaction-manager=”transactionManager” proxy-target-class=”true”/

!– 測試Service —

bean id=”loginService” class=”service.LoginService”/bean

!– 測試Dao —

bean id=”hibernateDao” class=”dao.HibernateDao”

property name=”sessionFactory” ref=”sessionFactory”/property

/bean

/beans

二、詳解

Spring MVC與Struts從原理上很相似(都是基於MVC架構),都有一個控制頁面請求的Servlet,處理完後跳轉頁面。看如下代碼(註解):

package controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import entity.User;

@Controller //類似Struts的Action

public class TestController {

@RequestMapping(“test/login.do”) // 請求url地址映射,類似Struts的action-mapping

public String testLogin(@RequestParam(value=”username”)String username, String password, HttpServletRequest request) {

// @RequestParam是指請求url地址映射中必須含有的參數(除非屬性required=false)

// @RequestParam可簡寫為:@RequestParam(“username”)

if (!”admin”.equals(username) || !”admin”.equals(password)) {

return “loginError”; // 跳轉頁面路徑(默認為轉發),該路徑不需要包含spring-servlet配置文件中配置的前綴和後綴

}

return “loginSuccess”;

}

@RequestMapping(“/test/login2.do”)

public ModelAndView testLogin2(String username, String password, int age){

// request和response不必非要出現在方法中,如果用不上的話可以去掉

// 參數的名稱是與頁面控件的name相匹配,參數類型會自動被轉換

if (!”admin”.equals(username) || !”admin”.equals(password) || age 5) {

return new ModelAndView(“loginError”); // 手動實例化ModelAndView完成跳轉頁面(轉發),效果等同於上面的方法返回字符串

}

return new ModelAndView(new RedirectView(“../index.jsp”)); // 採用重定向方式跳轉頁面

// 重定向還有一種簡單寫法

// return new ModelAndView(“redirect:../index.jsp”);

}

@RequestMapping(“/test/login3.do”)

public ModelAndView testLogin3(User user) {

// 同樣支持參數為表單對象,類似於Struts的ActionForm,User不需要任何配置,直接寫即可

String username = user.getUsername();

String password = user.getPassword();

int age = user.getAge();

if (!”admin”.equals(username) || !”admin”.equals(password) || age 5) {

return new ModelAndView(“loginError”);

}

return new ModelAndView(“loginSuccess”);

}

@Resource(name = “loginService”) // 獲取applicationContext.xml中bean的id為loginService的,並注入

private LoginService loginService; //等價於spring傳統注入方式寫get和set方法,這樣的好處是簡潔工整,省去了不必要得代碼

@RequestMapping(“/test/login4.do”)

public String testLogin4(User user) {

if (loginService.login(user) == false) {

return “loginError”;

}

return “loginSuccess”;

}

}

以上4個方法示例,是一個Controller里含有不同的請求url,也可以採用一個url訪問,通過url參數來區分訪問不同的方法,代碼如下:

package controller;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

@Controller

@RequestMapping(“/test2/login.do”) // 指定唯一一個*.do請求關聯到該Controller

public class TestController2 {

@RequestMapping

public String testLogin(String username, String password, int age) {

// 如果不加任何參數,則在請求/test2/login.do時,便默認執行該方法

if (!”admin”.equals(username) || !”admin”.equals(password) || age 5) {

return “loginError”;

}

return “loginSuccess”;

}

@RequestMapping(params = “method=1”, method=RequestMethod.POST)

public String testLogin2(String username, String password) {

// 依據params的參數method的值來區分不同的調用方法

// 可以指定頁面請求方式的類型,默認為get請求

if (!”admin”.equals(username) || !”admin”.equals(password)) {

return “loginError”;

}

return “loginSuccess”;

}

@RequestMapping(params = “method=2”)

public String testLogin3(String username, String password, int age) {

if (!”admin”.equals(username) || !”admin”.equals(password) || age 5) {

return “loginError”;

}

return “loginSuccess”;

}

}

其實RequestMapping在Class上,可看做是父Request請求url,而RequestMapping在方法上的可看做是子Request請求url,父子請求url最終會拼起來與頁面請求url進行匹配,因此RequestMapping也可以這麼寫:

package controller;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping(“/test3/*”) // 父request請求url

public class TestController3 {

@RequestMapping(“login.do”) // 子request請求url,拼接後等價於/test3/login.do

public String testLogin(String username, String password, int age) {

if (!”admin”.equals(username) || !”admin”.equals(password) || age 5) {

return “loginError”;

}

return “loginSuccess”;

}

}

用Javassist修改方法的幾個問題

以通過一種手段來在程序內部來修改授權部分的實現,使真實的授權部分隱藏在其它代碼部分,而可視的授權代碼並不參與實際的授權授權,這樣的話,對於破解者來說,修改表向的代碼實現並不能真正修改代碼實現,因為真實的實現已經通過其它代碼將原始實現替換掉了。

即在調用授權代碼之前將授權原代碼進行修改,然後調用授權代碼時即調用已經修改後的授權代碼,而真實的授權代碼是查看不了的(通過某種方式注入),這樣即達到一種授權方式的隱藏。

可以通過javassist來修改java類的一個方法,來修改一個方法的真實實現。修改的方法可以是動態方法,也可以是靜態方法。修改的前提即是當前修改的類還沒有被當前jvm加載,如果當前的類已經被加載,則不能修改。

ClassPool classPool = ClassPool.getDefault();

     CtClass ctClass = classPool.get(“com.develop.Txt”);

CtMethod ctMethod = ctClass.getDeclaredMethod(“i”);

ctMethod.setBody(“{try{Integer i = null;”

+ “int y = i.intValue();System.out.println(\”this is a new method\”);”);

ctClass.toClass();

上面的方法即是修改一個方法的實現,當調用ctClass.toClass()時,當前類即會被當前的classLoader加載,並實例化類。

需要注意的是,在調用ctClass.toClass()時,會加載此類,如果此類在之前已經被加載過,則會報一個duplicate load的錯誤,表示不能重複加載一個類。所以,修改方法的實現必須在修改的類加載之前進行。

    即使不調用toClass,那麼如果當前修改的類已經加載,那麼修改方法實現,同樣不起作用,即修改一個已經加載的類(不論是修改靜態方法,還是修改動態方法)是沒有任何效果的。修改之前必須在類加載之前進行。

    當然,使用aspectj也可以同樣達到修改的效果,不過修改指定的類,則需要為修改這個類添加一個aspect,然後將這個aspect加入配置文件中以使其生效,比起javassist來說,修改一個類還是使用javassist相對簡單一點。

用JAVASSIST如何得到一個類中所有的內部類(inner class)?

內部類:內部類也就是定義在類內部的類。

內部類的分類:成員內部類、局部內部類、 靜態內部類、匿名內部類

成員內部類

四個訪問權限修飾符都可以修飾成員內部類。

內部類和外部類在編譯時時不同的兩個類,內部類對外部類沒有任何依賴。

內部類是一種編譯時語法,在編譯時生成的各自的位元組碼文件,內部類和外部類沒有關係。

內部類中可以訪問外部類的私有成員。

作為外部類的一個成員存在,與外部類的屬性、方法並列。

內部類和外部類的實例變量可以共存。

在內部類中訪問實例變量:this.屬性

在內部類訪問外部類的實例變量:外部類名.this.屬性。

在外部類的外部訪問內部類,使用out.inner.

成員內部類的特點:

1.內部類作為外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明為private,但是對於處於其內部的內部類還是可見的。)

2.用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。

注意:內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩類。

對於一個名為outer的外部類和其內部定義的名為inner的內部類。編譯完成後出現outer.class和outer$inner.class兩類。

3.成員內部類不能含有靜態成員。

建立內部類對象時應注意:

在外部類的內部可以直接使用inner s=new inner();(因為外部類知道inner是哪個類,所以可以生成對象。)

而在外部類的外部,要生成(new)一個內部類對象,需要首先建立一個外部類對象(外部類可用),然後在生成一個內部類對象。內部類的類名是外部類類名.內部類類名。

Outer o=new Outer();

Outer.Inner in=o.new.Inner()。

靜態內部類

(注意:前三種內部類與變量類似,所以可以對照參考變量)

靜態內部類定義在類中,任何方法外,用static class定義。

靜態內部類只能訪問外部類的靜態成員。

生成(new)一個靜態內部類不需要外部類成員:這是靜態內部類和成員內部類的區別。

靜態內部類的對象可以直接生成:

Outer.Inner in=new Outer.Inner();

而不需要通過生成外部類對象來生成。這樣實際上使靜態內部類成為了一個頂級類。靜態內部類不可用private來進行定義。

注意:當類與接口(或者是接口與接口)發生方法命名衝突的時候,此時必須使用內部類來實現。

用接口不能完全地實現多繼承,用接口配合內部類才能實現真正的多繼承。

例子:

對於兩個類,擁有相同的方法:

class People

{

run();

}

interface Machine{

run();

}

此時有一個robot類:

class Robot extends People implement Machine.

此時run()不可直接實現。

interface Machine

{

void run();

}

class Person

{

void run(){System.out.println(“run”);}

}

class Robot extends Person

{

private class MachineHeart implements Machine

{

public void run(){System.out.println(“heart run”);}

}

public void run(){System.out.println(“Robot run”);}

Machine getMachine(){return new MachineHeart();}

}

class Test

{

public static void main(String[] args)

{

Robot robot=new Robot();

Machine m=robot.getMachine();

m.run();

robot.run();

}

}

局部內部類

在方法中定義的內部類稱為局部內部類。

與局部變量類似,在局部內部類前不加修飾符public和private,其範圍為定義它的代碼塊。

注意:局部內部類不僅可以訪問外部類私有實例變量,但可以訪問外部類的局部常量(也就是局部變量必須為final的)

在類外不可直接訪問局部內部類(保證局部內部類對外是不可見的)。

在方法中才能調用其局部內部類。

通過內部類和接口達到一個強制的弱耦合,用局部內部類來實現接口,並在方法中返回接口類型,使局部內部類不可見,屏蔽實現類的可見性。

局部內部類寫法

public class TestLocalInnerClass{

public static void main(String[] args){

Outer o=new Outer();

final int a=9;

o.print(a);

}

}

class Outer{

private int index=100;

public void print(final int a){

final int b=10;

System.out.println(a);

class Inner{

public void print(){

System.out.println(index);

System.out.println(a);

System.out.println(b);

}

}

Inner i=new Inner();

i.print();

}

}

匿名內部類

匿名內部類是一種特殊的局部內部類,它是通過匿名類實現接口。

匿名內部類的特點:

1,一個類用於繼承其他類或是實現接口,並不需要增加額外的方法,只是對繼承方法的事先或是覆蓋。

2,只是為了獲得一個對象實例,不許要知道其實際類型。

3,類名沒有意義,也就是不需要使用到。

註:一個匿名內部類一定是在new的後面,用其隱含實現一個接口或實現一個類,沒有類名,根據多態,我們使用其父類名。

因其為局部內部類,那麼局部內部類的所有限制都對其生效。

匿名內部類是唯一一種無構造方法類。

大部分匿名內部類是用於接口回調用的。

匿名內部類在編譯的時候由系統自動起名Out$1.class。

如果一個對象編譯時的類型是接口,那麼其運行的類型為實現這個接口的類。

因匿名內部類無構造方法,所以其使用範圍非常的有限。

當需要多個對象時使用局部內部類,因此局部內部類的應用相對比較多。匿名內部類中不能定義構造方法。

匿名內部類的寫法:

interface A{

void ia();

}

class B{

public A bc(){

return new A{

void ia(){

}

};

}

}

使用匿名內部類:

B b=new B();

A a=b.bc();

a.ia();

javassist-3.11.0.GA.jar 起什麼作用

Javassist的(JAVA編程助手)使Java位元組碼操縱簡單。這是一個編輯Java位元組碼的類庫。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/243440.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:56
下一篇 2024-12-12 12:56

相關推薦

  • Python生成隨機數的應用和實例

    本文將向您介紹如何使用Python生成50個60到100之間的隨機數,並將列舉使用隨機數的幾個實際應用場景。 一、生成隨機數的代碼示例 import random # 生成50個6…

    編程 2025-04-29
  • Python簡單數學計算

    本文將從多個方面介紹Python的簡單數學計算,包括基礎運算符、函數、庫以及實際應用場景。 一、基礎運算符 Python提供了基礎的算術運算符,包括加(+)、減(-)、乘(*)、除…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • Python海龜代碼簡單畫圖

    本文將介紹如何使用Python的海龜庫進行簡單畫圖,並提供相關示例代碼。 一、基礎用法 使用Python的海龜庫,我們可以控制一個小海龜在窗口中移動,並利用它的「畫筆」在窗口中繪製…

    編程 2025-04-29
  • Python櫻花樹代碼簡單

    本文將對Python櫻花樹代碼進行詳細的闡述和講解,幫助讀者更好地理解該代碼的實現方法。 一、簡介 櫻花樹是一種圖形效果,它的實現方法比較簡單。Python中可以通過turtle這…

    編程 2025-04-28
  • Python大神作品:讓編程變得更加簡單

    Python作為一種高級的解釋性編程語言,一直被廣泛地運用於各個領域,從Web開發、遊戲開發到人工智能,Python都扮演着重要的角色。Python的代碼簡潔明了,易於閱讀和維護,…

    編程 2025-04-28
  • 如何在dolphinscheduler中運行chunjun任務實例

    本文將從多個方面對dolphinscheduler運行chunjun任務實例進行詳細的闡述,包括準備工作、chunjun任務配置、運行結果等方面。 一、準備工作 在運行chunju…

    編程 2025-04-28
  • 用Python實現簡單爬蟲程序

    在當今時代,互聯網上的信息量是爆炸式增長的,其中很多信息可以被利用。對於數據分析、數據挖掘或者其他一些需要大量數據的任務,我們可以使用爬蟲技術從各個網站獲取需要的信息。而Pytho…

    編程 2025-04-28
  • 如何製作一個簡單的換裝遊戲

    本文將從以下幾個方面,為大家介紹如何製作一個簡單的換裝遊戲: 1. 遊戲需求和界面設計 2. 使用HTML、CSS和JavaScript開發遊戲 3. 實現遊戲的基本功能:拖拽交互…

    編程 2025-04-27
  • Guava Limiter——限流器的簡單易用

    本文將從多個維度對Guava Limiter進行詳細闡述,介紹其定義、使用方法、工作原理和案例應用等方面,並給出完整的代碼示例,希望能夠幫助讀者更好地了解和使用該庫。 一、定義 G…

    編程 2025-04-27

發表回復

登錄後才能評論