Day30-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\annotation\Proxy
反射
package Basic.src.com.reflect;
import org.junit.Test;
import java.lang.reflect.Method;
public class Test4Method {
@Test
public void testGetMethhod() throws Exception {
//1.反射第一步:先得到Class對象
Class cat = Cat.class;
//2.獲取類的全部成員方法
Method[] methods = cat.getDeclaredMethods();
//3.遍歷這個數組中的每個方法對象
for (Method method : methods) {
System.out.println(method.getName()+"------------"
+method.getParameterCount()+"------------"
+method.getReturnType());
}
//4.獲取某個方法對象
Method run = cat.getDeclaredMethod("run");//拿run(),無參的
System.out.println(run.getName()+"------------"
+run.getParameterCount()+"------------"
+run.getReturnType());
Cat cat1 = new Cat();
run.setAccessible(true);//暴力反射public void run()即使是private也可以訪問
Object rs = run.invoke(cat1);//調用方法
System.out.println(rs);//null
System.out.println("====================================");
Method eat = cat.getDeclaredMethod("eat", String.class);
System.out.println(eat.getName()+"------------"
+eat.getParameterCount()+"------------"
+eat.getReturnType());
eat.setAccessible(true);//private String eat(String name)
String es = (String)eat.invoke(cat1,"魚");
System.out.println(es);//耄耄最愛食:魚
System.out.println(eat);//private java.lang.String Basic.src.com.reflect.Cat.eat(java.lang.String)
}
}
package Basic.src.com.reflect;
import org.junit.Test;
public class Test5Frame {
@Test
public void save() throws Exception {
Student s1 = new Student("哈基濱", 22, '公', 185.3, "唱跳rap");
Teacher t1 = new Teacher("南北綠豆", 999.9);
//需求:把任意對象的字段名稱和其對應的值等信息,保存到文件中去
ObjectFrame.saveObject(s1);
ObjectFrame.saveObject(t1);
}
}
package Basic.src.com.reflect;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class ObjectFrame {
//目標:保存任意對象的字段和其數據到文件中去
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("Basic\\src\\data.txt",true));
//1.obj是任意對象,到底有多少個字段要保存。
Class<?> c = obj.getClass();
String cName = c.getSimpleName();
ps.println("------------------"+cName+"------------------");
//2.從這個類中提取它的全部成員變量
Field[] fields = c.getDeclaredFields();
//3.遍歷每個成員變量
for (Field field : fields) {
//4.拿到成員變量的名字
String name = field.getName();
//5.拿到這個成員變量在對象中的數據
field.setAccessible(true);//授權
String value = field.get(obj)+"";//+""轉為String類型
ps.println(name+"="+value);
}
ps.close();
}
}
注解
注解本質上接口,繼承了annotation
package Basic.src.com.annotation;
@MyTest1(aaa="牛魔王",ccc={"HTML","JAVA"})
@MyTest2("孫悟空")//當只有一個未默認化的屬性并且叫value,那么value可以省略
public class AnnotationTest1 {
@MyTest1(aaa="鐵山公主",bbb=false,ccc={"Python","前端","Java"})
public void test1(){
System.out.println("test1");
}
public static void main(String[] args) {
//執行后會把上面的注解從java文件編譯為class后綴的文件
//"C:\Users\Lenovo\Desktop\note\code\JavaSE\out\production\JavaSE\Basic\src\com\annotation\MyTest1.class"
}
}
package Basic.src.com.annotation;
/**
* 自定義注解
*/
public @interface MyTest1 {
String aaa();
boolean bbb() default true;
String[] ccc();
}
package Basic.src.com.annotation;
public @interface MyTest2 {
String value();//特殊屬性
int age() default 0;
}
元注解
指的是:修飾注解的注解
@Target @Retention
package Basic.src.com.annotation;
/*
* 元注解
* */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})//當前被修飾的注解只能被用在類上
@Retention(RetentionPolicy.RUNTIME)//只在運行階段,常用
public @interface MyTest3 {
}
package Basic.src.com.annotation;
/*
* 元注解
* */
@MyTest3
public class AnnotationTest2 {
//@MyTest3報錯,這個是成員變量
private String name;
@MyTest3//不報錯,這個是方法
public void test(){
}
}
package Basic.src.com.annotation;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
public class AnnotationTest3 {
@Test
public void parseClass() {
//1.先得到class類對象
Class<Demo> c = Demo.class;
//2.解析上面的注解
//判斷這個類上面是不是包含了某個注解
if(c.isAnnotationPresent(MyTest4.class)){//MyTest4.class)是填進去的注解類型
MyTest4 myTest4 =
c.getDeclaredAnnotation(MyTest4.class);//就是Demo類里面有沒有MyTest4這個注解
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
Annotation[] da = c.getDeclaredAnnotations();
for (Annotation annotation : da) {
}
}
@Test
public void parseMethod() throws Exception {
//1.先得到class類對象
Class<Demo> c = Demo.class;
Method m = c.getDeclaredMethod("test1");
//2.解析上面的注解
//判斷這個"test1"測試方法對象上面是不是包含了某個注解
if(m.isAnnotationPresent(MyTest4.class)){//MyTest4.class)是填進去的注解類型
MyTest4 myTest4 =
c.getDeclaredAnnotation(MyTest4.class);//就是Demo類里面有沒有MyTest4這個注解
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
}
package Basic.src.com.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4 {
String value();
double aaa() default 100;
String[] bbb();
}
package Basic.src.com.annotation;
@MyTest4(value="蜘蛛精",aaa=99.5,bbb={"至尊寶","黑馬"})
public class Demo {
@MyTest4(value="哈基濱",aaa=66.6,bbb={"叮咚雞","大狗嚼嚼嚼"})
public void test1(){
System.out.println("test1");
}
}
package Basic.src.com.annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 目標:模擬Junit框架的設計
*/
public class AnnotationTest4 {
//@MyTest
public void test1(){
System.out.println("test1");
}
@MyTest
public void test2(){
System.out.println("test2");
}
public void test3(){
System.out.println("test3");
}
@MyTest
public void test4(){
System.out.println("test4");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
AnnotationTest4 a = new AnnotationTest4();
//實現啟動程序
//1.得到class對象
Class<AnnotationTest4> c = AnnotationTest4.class;
//2.提取這個類中的全部成員方法
Method[] Methods = c.getDeclaredMethods();
//3.遍歷這個數組中的每個方法,看方法是是否存在
//觸發該方法的執行
for (Method method : Methods) {
if(method.isAnnotationPresent(MyTest.class)){
//說明當前方法上存在該注解,觸發該方法執行
method.setAccessible(true);
method.invoke(a);
// Method.invoke() 方法時,括號中第一個參數需要傳入的是調用該方法的對象實例(即方法所屬的對象),其作用是指定 “在哪個對象上執行當前方法”。
}
}
}
}
package Basic.src.com.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest {
}
動態代理
package Basic.src.com.annotation.Proxy;
public class BigStar implements Star {// implements Star是生成代理的約定{
private String name;
public BigStar(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String sing(String name) {
System.out.println(this.name + "正在唱:" + name);
return "thank you!";
}
public void dance(){
System.out.println(this.name+"正在唱跳rap");
}
}
package Basic.src.com.annotation.Proxy;
public interface Star {
//先聲明哪些方法要被代理
String sing(String name);
void dance();
}
package Basic.src.com.annotation.Proxy;
public class BigStar implements Star {// implements Star是生成代理的約定{
private String name;
public BigStar(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String sing(String name) {
System.out.println(this.name + "正在唱:" + name);
return "thank you!";
}
public void dance(){
System.out.println(this.name+"正在唱跳rap");
}
}
package Basic.src.com.annotation.Proxy;
public interface Star {
//先聲明哪些方法要被代理
String sing(String name);
void dance();
}
package Basic.src.com.annotation.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static Star createProxy(BigStar bigStar){
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class}, new InvocationHandler() {//創建一個實現了 Star 接口的動態代理對象 starProxy
//ProxyUtil 是你自己編寫的類(位于 Basic.src.com.annotation.Proxy 包下),它的類加載器是 應用類加載器(AppClassLoader),負責加載用戶編寫的類(包括你的 Star 接口、BigStar 類等)。
//因此,ProxyUtil 的類加載器與 Star 接口的類加載器是同一個(或存在父子關系,符合雙親委派模型),它們屬于同一個 “命名空間”。
@Override //回調方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//我們的代理對象要做的事情
//Object proxy 代理對象本身:starProxy 對象本身
//Method method 調用的什么函數,比如sing dance
//Object[] args 存儲了客戶端調用代理對象方法時傳入的實際參數值,調用的比如sing方法里面的參數
if(method.getName().equals("sing")){
System.out.println("準備話筒,收錢");
//return method.invoke(bigStar,args);//args指的可能是唱哪首歌對應的參數
}else if(method.getName().equals("dance")){
System.out.println("準備場地,收錢");
//return method.invoke(bigStar,args);
}else {
//return method.invoke(bigStar,args);
}
return method.invoke(bigStar,args);//調用BigStar里面的該method對應的方法
}
});//創建代理Proxy.newProxyInstance
/*
* ClassLoader loader,指定一個類加載器,生成一個代理類(固定)
Class<?>[] interfaces,指定生成的代理長什么樣,有什么方法,接收多個數組(接口數組里面的方法就可以被接收)
InvocationHandler h指定生成的代理對象要干什么事情,代理干什么事情是由這個決定的
* */
return starProxy;
}
}
package Basic.src.com.annotation.Proxy;
public class TestStar {
public static void main(String[] args) {
BigStar s = new BigStar("楊超越");
Star starProxy = ProxyUtil.createProxy(s);//ProxyUtil類是我們自己編寫的,里面有createProxy方法
//創建代理對象,把s傳進去,這個工具類就為楊超越類創建了一個代理對象
String rs = starProxy.sing("好日子");//這里的sing方法會調用代理ProxyUtil類中的invoke方法,這里是接口回調
System.out.println(rs);
starProxy.dance();
}
}
改造
package Basic.src.com.annotation.Proxy.Exercise;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {//代理對應規則
public static UserService createUserService(UserService userService){
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{UserService.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("login")||method.getName().equals("deleteUsers")||method.getName().equals("selectUsers")){
long startTime = System.currentTimeMillis();
Object rs = method.invoke(userService, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+"方法執行耗時"+(endTime-startTime)+"ms");
return rs;
}else{
Object rs = method.invoke(userService, args);
return rs;
}
}
});
return userServiceProxy;
}
}
package Basic.src.com.annotation.Proxy.Exercise;
public interface UserService {
//登錄功能
void login(String name,String password)throws Exception;
//刪除用戶
void deleteUsers()throws Exception;
//查詢用戶,返回數組的形式
String[] selectUsers()throws Exception;
}
package Basic.src.com.annotation.Proxy.Exercise;
public class UserServiceimpl implements UserService {
@Override
public void login(String name, String password) throws Exception {
if("admin".equals(name) && "123456".equals(password)){
System.out.println("登錄成功,歡迎光臨本系統");
}else{
System.out.println("登錄失敗,用戶名或密碼錯誤");
}
Thread.sleep(1000);
}
@Override
public void deleteUsers() throws Exception {
System.out.println("成功刪除了一萬個用戶");
Thread.sleep(1500);
}
@Override
public String[] selectUsers() throws Exception {
System.out.println("查詢出了三個用戶");
String[] names = {"張三","李四","王五"};
Thread.sleep(500);
return names;
}
}
package Basic.src.com.annotation.Proxy.Exercise;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws Exception {
//1.創建用戶業務對象
//UserService userService = new UserServiceimpl();//接口是 “類” 的一種特殊形式,這個沒有計時功能
UserService userService = ProxyUtil.createUserService(new UserServiceimpl());
//2.調用用戶業務的功能
userService.login("admin","123456");//下面都是代理的代碼
System.out.println("===========================");
userService.deleteUsers();
System.out.println("===========================");
String[] names = userService.selectUsers();
System.out.println("查詢到的用戶是:"+ Arrays.toString(names));
System.out.println("===========================");
}
}

浙公網安備 33010602011771號