对于Aspect-OrientedProgramming:Aspect-OrientedProgrammingwiththeRealProxyClass感兴趣的读者,本文将提供您所需要的所有信息,并且
对于Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class感兴趣的读者,本文将提供您所需要的所有信息,并且为您提供关于159.234 OBJECT-ORIENTED PROGRAMMING、AlgorithmPartI:ProgrammingAssignment(2)、An Introduction to Protocol Oriented Programming in Swift、AOP(Aspect Oriented Programing) "面向切面编程"的宝贵知识。
本文目录一览:- Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class
- 159.234 OBJECT-ORIENTED PROGRAMMING
- AlgorithmPartI:ProgrammingAssignment(2)
- An Introduction to Protocol Oriented Programming in Swift
- AOP(Aspect Oriented Programing) "面向切面编程"
Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class
Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class
A well-architected application has separate layers so different concerns don’t interact more than needed. Imagine you’re designing a loosely coupled and maintainable application,but in the middle of the development,you see some requirements that might not fit well in the architecture,such as:
- The application must have an authentication system,used before any query or update.
- The data must be validated before it’s written to the database.
- The application must have auditing and logging for sensible operations.
- The application must maintain a debugging log to check if operations are OK.
- Some operations must have their performance measured to see if they’re in the desired range.
Any of these requirements need a lot of work and,more than that,code duplication. You have to add the same code in many parts of the system,which goes against the “don’t repeat yourself” (DRY) principle and makes maintenance more difficult. Any requirement change causes a massive change in the program. When I have to add something like that in my applications,I think,“Why can’t the compiler add this repeated code in multiple places for me?” or,“I wish I had some option to ‘Add logging to this method.’”
The good news is that something like that does exist: aspect-oriented programming (AOP). It separates general code from aspects that cross the boundaries of an object or a layer. For example,the application log isn’t tied to any application layer. It applies to the whole program and should be present everywhere. That’s called a crosscutting concern.
AOP is,according to Wikipedia,“a programming paradigm that aims to increase modularity by allowing the separation of crosscutting concerns.” It deals with functionality that occurs in multiple parts of the system and separates it from the core of the application,thus improving separation of concerns while avoiding duplication of code and coupling.
In this article,I’ll explain the basics of AOP and then detail how to make it easier by using a dynamic proxy via the Microsoft .NET Framework class RealProxy.
159.234 OBJECT-ORIENTED PROGRAMMING
159.234 OBJECT-ORIENTED PROGRAMMING S1, 2024
Assignment 3
Deadline: 4 June 2024, 11pm
Evaluation: 40 marks (20% of your final grade)
Late Submission: Deduct 4 marks per day late
Individual Work You must complete this assignment by yourself (you must NOT share your code
with others or use others’ code)
Purpose: Reinforce Java OOP core concepts (abstraction, encapsulation, inheritance, and
polymorphism), collections framework and generics, exception handling, input and
output streams, and GUI using Swing
- System Description (Overview of Problem)
You are asked to write a program in Java to simulate a computer store’s management system
A computer store maintains three categories of computers: Desktop PCs, Laptops, and Tablets. Each
category is further divided into different types, as listed below:
Desktop PC types: Gaming, Home & Study, Business, and Compact
Laptop types: Gaming, Home & Study, Business, and Thin & Light
Tablet types: Android, Apple, and Windows
Each computer’s unique ID, brand, CPU family, and price need to be specified regardless of its category.
The computer store must also record memory size (GB) and SSD capacity (GB) for Desktop PCs and
Laptops as well as screen size (inches) for Laptops and Tablets.
The computer store has two types of staff: salespersons and managers. A salesperson can log into the
computer store’s management system to view a list of all computers. A salesperson can also search for
computers by category and type before clicking on a search result to view that computer’s details.
A manager can log into the computer store’s management system to do everything that a salesperson can
do, but a manager can also maintain records—by updating computer details or adding and deleting
computers.
- Tasks to complete:
a) Create a narrative step-by-step storyboard using screenshots of your system-generated GUIs to
demonstrate required functions of the computer store’s management system (please refer to a
sample at the end of this document; you can use its format to present your work)
Your Java code should:
b) Import the provided test data (computers.txt) to your system using Java Input
c) Add five staff to the computer store’s system—three salespersons and two managers—using 写159.234 OBJECT-ORIENTED PROGRAMMINGusernames
and passwords provided (this function should have classes designed with an appropriate inheritance
hierarchy that applies core OOP concepts)
d) Realize all functions specified in the system description above (for this assignment, you are NOT
required to update computers.txt file after a manager update/add/delete records, you only need to
update the GUI to show the change)
Design and Implementation Guidelines
Note: You will receive credit for correctness, completeness, no code duplication, and clear on-screen outputs.
Also, we will grade your program using the following OOP and general software implementation
guidelines:1) Encapsulation design and implementation—proper use of modifiers
a. Private/Protected/Public
b. Must make use of getters and/or setters wherever appropriate
159.234 OBJECT-ORIENTED PROGRAMMING S1, 2024
2) Inheritance design and implementation
a. Reasonable class hierarchies
b. Proper data fields separation in base and derived classes
c. Proper methods separation/overloading/overriding in base and derived classes
d. Proper use of base and derived class constructors
3) Polymorphism and implementation
a. Write generic code that targets the base class whenever possible
b. Appropriate use of overriding in derived classes to realize polymorphism
4) Information store and implementation
a. Use HashMap and other Java collection class(es) to store information
5) Exception handling
a. Throw an exception object when an application error occurs (e.g., when an invalid piece of data is
entered)
b. Use “try/catch/finally” or “try/catch” block to handle the exception
6) Use Java Swing to implement your GUI
- Other Specifications
You must follow the next three specifications when completing this assignment:
1) Place appropriate comments in your program—e.g.:
/* explain what the program file is doing . . . /
// explain what a part/method of the program is doing…
2) DO NOT add any file path for ‘computers.txt’ (put it directly in your project folder when you test your
code)
3) DO NOT add your own package name(s) to the beginning of your .java files (this requirement is only
for marking purpose)
- Submission Requirements:
1) Your storyboard as a PDF file
2) All your .java files (source codes)
3) Any image file(s) you may have used in your program (put the image file(s) directly in your project
folder when you test your code - this requirement is only for marking purposes).
4) Zip all your files from 1), 2), and 3) together and submit as a single file to Stream - You MUST use the following test data in your assignment:
1) Staff details
Usernames Passwords
Staff 1 – Salesperson p1 p1
Staff 2 – Salesperson p2 p2
Staff 3 – Salesperson p3 p3
Staff 4 – Manager m1 m1
Staff 5 – Manager m2 m2
159.234 OBJECT-ORIENTED PROGRAMMING S1, 2024
2) Input file computers.txt to download
3) Example GUI and functions narrations:
Note: this is just a sample GUI design; you are free to design your own GUI and function flow as long
as they are reasonable and complete the tasks listed in item “2.” above
When the program runs:
WX:codinghelp
AlgorithmPartI:ProgrammingAssignment(2)
问题描述: Programming Assignment 2: Randomized Queues and Deques Write a generic data type for a deque and a randomized queue. The goal of this assignment is to implement elementary data structures using arrays and linked lists, and to int
问题描述:
Programming Assignment 2: Randomized Queues and Deques
Write a generic data type for a deque and a randomized queue. The goal of this assignment is to implement elementary data structures using arrays and linked lists, and to introduce you to generics and iterators.
Dequeue. A double-ended queue or deque (pronounced "deck") is a generalization of a stack and a queue that supports inserting and removing items from either the front or the back of the data structure. Create a generic data type Deque that implements the following API:
public class Deque implements Iterable { public Deque() // construct an empty deque public boolean isEmpty() // is the deque empty? public int size() // return the number of items on the deque public void addFirst(Item item) // insert the item at the front public void addLast(Item item) // insert the item at the end public Item removeFirst() // delete and return the item at the front public Item removeLast() // delete and return the item at the end public Iterator iterator() // return an iterator over items in order from front to end public static void main(String[] args) // unit testing }
Throw a NullPointerException if the client attempts to add a null item; throw a java.util.NoSuchElementException if the client attempts to remove an item from an empty deque; throw an UnsupportedOperationException if the client calls the remove() method in the iterator; throw a java.util.NoSuchElementException if the client calls the next() method in the iterator and there are no more items to return.
Your deque implementation must support each deque operation in constant worst-case time and use space proportional to the number of items currently in the deque. Additionally, your iterator implementation must support the operations next() and hasNext() (plus construction) in constant worst-case time and use a constant amount of extra space per iterator.
Randomized queue. A randomized queue is similar to a stack or queue, except that the item removed is chosen uniformly at random from items in the data structure. Create a generic data type RandomizedQueue that implements the following API:
<strong>public class RandomizedQueue<Item> implements Iterable<Item> { public RandomizedQueue() </strong>// construct an empty randomized queue <strong> public boolean isEmpty() </strong>// is the queue empty? <strong> public int size() </strong>// return the number of items on the queue <strong> public void enqueue(Item item) </strong>// add the item <strong> public Item dequeue() </strong>// delete and return a random item <strong> public Item sample() </strong>// return (but do not delete) a random item <strong> public Iterator<Item> iterator() </strong>// return an independent iterator over items in random order <strong> public static void main(String[] args) </strong>// unit testing <strong>}</strong>登录后复制
Throw a NullPointerException if the client attempts to add a null item; throw a java.util.NoSuchElementException if the client attempts to sample or dequeue an item from an empty randomized queue; throw anUnsupportedOperationException if the client calls the remove() method in the iterator; throw a java.util.NoSuchElementException if the client calls the next() method in the iterator and there are no more items to return.
Your randomized queue implementation must support each randomized queue operation (besides creating an iterator) in constant amortized time and use space proportional to the number of items currently in the queue. That is, any sequence of M randomized queue operations (starting from an empty queue) should take at most cM steps in the worst case, for some constant c. Additionally, your iterator implementation must support construction in time linear in the number of items and it must support the operations next() and hasNext() in constant worst-case time; you may use a linear amount of extra memory per iterator. The order of two or more iterators to the same randomized queue should be mutually independent; each iterator must maintain its own random order.
Subset client. Write a client program Subset.java that takes a command-line integer k; reads in a sequence of N strings from standard input using StdIn.readString(); and prints out exactly k of them, uniformly at random. Each item from the sequence can be printed out at most once. You may assume that 0 ≤ k ≤ N, where N is the number of string on standard input.
The running time of Subset must be linear in the size of the input. You may use only a constant amount of memory plus either one Deque or RandomizedQueue object of maximum size at most N, where N is the number of strings on standard input. (For an extra challenge, use only one Deque or RandomizedQueue object of maximum size at most k.) It should have the following API.% <strong>echo A B C D E F G H I | java Subset 3</strong> % <strong>echo AA BB BB BB BB BB CC CC | java Subset 8</strong> C BB G AA A BB CC % <strong>echo A B C D E F G H I | java Subset 3</strong> BB E BB F CC G BB登录后复制
<strong>public class Subset { public static void main(String[] args) }</strong>登录后复制
Deliverables. Submit only Deque.java, RandomizedQueue.java, and Subset.java. We will supply stdlib.jar. You may not use any libraries other than those in stdlib.jar, java.lang, java.util.Iterator, and java.util.NoSuchElementException.
代码:
Deque.java
import java.util.Iterator; ; public class Deque<Item> implements Iterable<Item> { private Node first; private Node last; private int length; public Deque() { first = null; last = null; length = 0; } public boolean isEmpty() { return length == 0; } public int size() { return length; } public void addFirst(Item item) { if (item == null) throw new NullPointerException(); if (length == 0) { Node newNode = new Node(); newNode.i = item; newNode.left = null; newNode.right = null; first = newNode; last = newNode; length++; } else { Node newNode = new Node(); newNode.i = item; newNode.right = null; newNode.left = first; first.right = newNode; first = newNode; length++; } } public void addLast(Item item) { if (item == null) throw new NullPointerException(); if (length == 0) { Node newNode = new Node(); newNode.i = item; newNode.left = null; newNode.right = null; first = newNode; last = newNode; length++; } else { Node newNode = new Node(); newNode.i = item; newNode.right = last; newNode.left = null; last.left = newNode; last = newNode; length++; } } public Item removeFirst() { if (isEmpty()) throw new java.util.NoSuchElementException(); if (length == 1) { Item item = first.i; first = null; last = null; length--; return item; } else { Item item = first.i; Node temp = first.left; first.left.right = null; first.left = null; first = temp; length--; return item; } } public Item removeLast() { if (isEmpty()) throw new java.util.NoSuchElementException(); if (length == 1) { Item item = first.i; first = null; last = null; length--; return item; } else { Item item = last.i; Node temp = last.right; last.right.left = null; last.right = null; last = temp; length--; return item; } } public static void main(String[] args) { // TODO Auto-generated method stub } @Override public Iterator<Item> iterator() { // TODO Auto-generated method stub return new ListIterator(); } private class Node { private Node left; private Node right; private Item i; } private class ListIterator implements Iterator<Item> { private Node ptr; private Item i; public ListIterator() { ptr = first; } @Override public boolean hasNext() { // TODO Auto-generated method stub if (ptr == null) return false; else return true; } @Override public Item next() { // TODO Auto-generated method stub if (!hasNext()) throw new java.util.NoSuchElementException(); else { i = ptr.i; ptr = ptr.left; return i; } } public void remove() { throw new UnsupportedOperationException(); } } }
RandomizedQueue.java
import java.util.Iterator; public class RandomizedQueue<Item> implements Iterable<Item> { private Item items[]; private int length; public RandomizedQueue() { items = (Item[]) new Object[2]; length = 0; } public boolean isEmpty() { return length == 0; } public int size() { return length; } public void enqueue(Item item) { if (item == null) throw new NullPointerException(); if (length == items.length) resize(items.length * 2); items[length] = item; length++; } public Item dequeue() { if (isEmpty()) throw new java.util.NoSuchElementException(); int n = (int) (Math.random() * length); Item i = items[n]; if (n != length - 1) items[n] = items[length - 1]; length--; if (length > 0 && length == items.length / 4) resize(items.length / 2); return i; } private void resize(int n) { Item newItem[] = (Item[]) new Object[n]; for (int i = 0; i < length; i++) newItem[i] = items[i]; items = newItem; } public Item sample() { if (isEmpty()) throw new java.util.NoSuchElementException(); int n = (int) (Math.random() * length); Item i = items[n]; return i; } @Override public Iterator<Item> iterator() { // TODO Auto-generated method stub return new ListIterator(); } private class ListIterator<Item> implements Iterator { int index; public ListIterator() { index = 0; } @Override public boolean hasNext() { // TODO Auto-generated method stub return index <= length - 1; } @Override public Object next() { // TODO Auto-generated method stub if (!hasNext()) throw new java.util.NoSuchElementException(); int n = (int) (Math.random()*(length-index)); Object item = items[n]; if(n != length-index-1) items[n] = items[length-index-1]; index++; return item; } public void remove() { throw new UnsupportedOperationException(); } } public static void main(String[] args) { // TODO Auto-generated method stub } }
public class Subset { public static void main(String[] args) { // TODO Auto-generated method stub RandomizedQueue rq = new RandomizedQueue(); int k = Integer.parseInt(args[0]); while (!StdIn.isEmpty()) rq.enqueue(StdIn.readString()); for (int i = 0; i < k; i++) StdOut.println(rq.dequeue()); } }
An Introduction to Protocol Oriented Programming in Swift
swift面向协议编程的根本原因在于值类型的存在;面向对象必须要有引用类型的支持;
Protocol Oriented approach was introduced to resolve some issues in programming and it also differs in varIoUs scenarios when compared to Object-Oriented programming. So let’s dive into the topic.
What is Protocol Oriented Programming?
Protocols basically serve as a blueprint like classes rather than a fully functional types for methods, properties, and other requirements. This is done to perform a piece of functionality and behaves like an interface and tells what to implement. It is a powerful feature of Swift Language. Apple tells us:
“Don’t Start with the Class, Start with the Protocol”
Why We Need POP?
When we design any software system, then we figure out the general requirements that satisfy the given system. We, even model the relationship b/w the UI elements such as buttons, view, images etc. for which we generally start with superclass and model the relationships using inheritance.
In Swift, as we have the concept of POP so, we can even start with protocols and can model the relationships as protocol implementations. In the protocol oriented approach, we model our system with a protocol, rely on the concepts like:
- Protocol Extensions
- Protocol Inheritance
- Protocol Composition
In Swift, we use structs, enums, and tuples rather than working only with classes since, Value Semantics are preferred over Reference Types.
Also, there Could be varIoUs cases where OOP is not the best solution to implement. Let’s check and figure out the drawbacks in Object-Oriented concept. We kNow that Inheritance is one of the most important concepts in OOP but, inheritance doesn’t work for value types and modern languages like Swift prohibits to support the feature of multiple inheritances due to complexities and value types is the first citizen of Swift. So, POP does a great job by providing the ability to add multiple abilities to the class, struct, and enum with protocols and extensions that supports multiple implementations while we code.
Other benefits with Protocol implementations are:
- Swift checks whether the requirements of the protocol are full-filled or not for the classes we are implementing at compile-time, so, this helps us to find out if there were any issues or bugs in code even before we ran our program.
- Also, protocols bring more abstraction mechanism than classes do in Swift.
- We’re not restricted to only use classes since any type, including value types, can implement a protocol.
- A type can implement multiple protocols.
- We can create as many protocols as we need.
Before I talk about POP in detail and how to use and implement it, we must understand the basics right, so let us focus on Swift Types first. Here is the diagrammatic representation of Swift Types that we have.
Well, here I am interested in the behavior of Classes and Structure, one belongs to the reference type and other to value type and observe how objects behave through an example.
And, this is really important to understand and why is it so? If you have a very complex hierarchy and you set something in one part of the code, it should not have any wrong consequences in the other part. So, the lesson is:
- Classes use reference i.e if you set something to other it is not a copy instead it is a reference.
- Whereas, in value type such as structures, passes things as a copy, not as a reference.
Conclusion
Apple, always recommends going with the value type while we program in Swift. Structures are preferable when we have a small copy of data and it is much safer than having multiple references to the same objects in our code. The concept becomes more important when we talk about variable and passing their value. In Swift, we work in a multi-threaded environment and if we have copies of variable then, we don’t need to worry about them in the other place where value may get change. So, using structure is advised by Apple and Protocol-Oriented Programming serves better abstraction with structures.
Using Protocols and it’s extensions features, we can really ignore/avoid for making a huge superclass and then inheriting functionality from there. So, Hope it is Now clear to you what is POP and why Apple use this.
Note: This does not mean that we don’t use Class, there are some situations where classes are the only option left for our implementation.
In the other part of this article, we will see how to implement and use protocols, protocol extensions, Generics with the protocol.
https://www.technotification.com/2018/08/protocol-oriented-programming-swift.html
AOP(Aspect Oriented Programing) "面向切面编程"
面向切面编程
通过横向抽取机制来解决类中的代码重复问题
- 代理目标(target)
- 被代理类实例代理的目标对象
- 代理对象(proxy)
- 代理其他类的对象
AOP中的概念
- 连接点(JoinPoint) :执行点+方位
- 执行点 :任意一个可执行的方法
- 切点(PoinCut)
- 对连接点进行筛选的条件 指定执行点和方位 确定在哪里添加代码
- Advice :在指定的切点所选择的连接点所加入的代码
- 切面(Aspect) :切面( Aspect ) = 切点( Pointcut ) + Advice
- 织入
- 将 Advice 对应的代码 加入到 切点 所选择的 连接点 的过程
- 实现方式:编译时织入 类加载时织入 运行期织入
- 方位
- 方法执行前(before)
/**
* 任意一个 Advice 对应的方法中 , 第一个参数都可以是 org.aspectj.lang.JoinPoint
* 通过 JoinPoint 可以在 Advice 对应的方法内部 访问 连接点 的信息
* 可以通过 JoinPoint 来访问 连接点 中的信息
*/
public void before (JoinPoint joinPoint){
Signature signature = joinPoint.getSignature();//获取 连接点 对应的方法的 签名
System.out.println("signature:"+signature);
int mod = signature.getModifiers();//获取 方法 的修饰符 返回值为整数
System.out.println("Modifier:"+Modifier.toString(mod));
System.out.println("Name:"+signature.getName());
Object[] args = joinPoint.getArgs();//获取被拦截方法在执行时接受的参数
System.out.println("args:"+ Arrays.toString( args ));
System.out.println( "【 " +joinPoint.getSignature().getName()+ "即将执行】" );
}
- 方法执行后(after)
- 方法执行前后(around)
public Object around( ProceedingJoinPoint joinPoint) throws Throwable { //joinPoint 必须是 ProceedingJoinPoint 类型
String name = joinPoint.getSignature().getName();
System.out.println( "开始为" + name + "计时" );
long begin = System.nanoTime();
Object result = joinPoint.proceed() ; // 通过 ProceedingJoinPoint 的 proceed 方法让被拦截的方法继续执行
long end = System.nanoTime();
System.out.println( "为" + name + "计时结束" );
System.out.println( "[ " + name + " ]执行耗时 [ " + ( end - begin ) + "ns, ]" );
return result ; // 返回 由 被拦截的方法执行后 所返回的值
}
- 方法正常返回后(after-return)
public void afterReturning (JoinPoint joinPoint ,Object returnValue){
System.out.println("【 "+ joinPoint.getSignature().getName()+" 】方法执行后返回了【"+returnValue+"】");
}
- 方法抛出异常后(after-throw)
spring配置文件
- AspectJ是语言级的AOP实现,AspectJ扩展了Java语言,能够在编译期提供横切代码的织入
- 添加 aspectj-runtime 和 aspectj-weaver 依赖并引入 aop 命名空间
- <aop:config proxy-target-> 是默认值 , 如果给定的类适合使用 JDK 动态代理来产生代理类,则采用JDK动态代理。否则采用 cglib 方式来创建
- <aop:config proxy-target-> 表示一律使用 cglib 方式来创建代理类
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http:"http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="advices"/>
//Advices 类中包含在指定切点 所选择的连接点 需要添加的方法
<aop:config>
<aop:aspect ref="advices">
//aspect 切面引入 需要添加的代码
<aop:pointcut id="firstpointcut" expression="execution(* com.it.aop.Fish.fly())"/> //aop:pointcut 选择 某个类中的某个方法 作为切点 第一个*表示修饰符和返回类型
<aop:after-returning method="afterReturning" pointcut-ref="firstpointcut" returning="returnValue"/> //在 引入的切点 的指定方位(after-returning)处添加Advices类中afterReturning方法 并指定 返回变量 returnValue
<aop:around method="around" pointcut-ref="firstpointcut"/>
<aop:before method="before" pointcut-ref="firstpointcut"/>
<aop:after method="after" pointcut-ref="firstpointcut"/>
</aop:aspect>
</aop:config>
- introdcation
- 在 aop:aspect </aop:aspect>中通过配置 declare-parents 为 Cat 类引入 HashMap的实现
<aop:declare-parents types-matching="com.it.aop.schema.Cat"
implement-interface="java.util.Map"
default-impl="java.util.HashMap"/>
<bean id="cat"p:name="Tom"/>
<aop:config proxy-target->
<aop:aspect>
<aop:declare-parents types-matching="com.it.aop.schema.Cat"
implement-interface="java.util.Map"
default-impl="java.util.HashMap"/>
</aop:aspect>
</aop:config>
</beans>
测试(Test)
- Fish 类实现了 flyable 接口
- <aop:config proxy-target-> 表示一律使用 cglib 方式来创建代理类
- 测试结果
【proxy.toString()】: Fish{com.it.aop.schema.Fish:230526532}
【proxy.getClass().getCanonicalName()】: com.it.aop.schema.Fish$$EnhancerBySpringCGLIB$$b63a9d5
【proxy.getClass().getSuperclass()】: class com.it.aop.schema.Fish
- <aop:config proxy-target-> 时测试结果
【proxy.toString()】: Fish{com.it.aop.schema.Fish:2005028997}
【proxy.getClass().getCanonicalName()】: com.sun.proxy.$Proxy6
【proxy.getClass().getSuperclass()】: class java.lang.reflect.Proxy
- Cat 类没有实现接口 proxy-target-/ "true" 测试结果相同
【proxy.toString()】: com.it.aop.schema.Cat@3e7dd664
【proxy.getClass().getCanonicalName()】: com.it.aop.schema.Cat$$EnhancerBySpringCGLIB$$42ce28ee
【proxy.getClass().getSuperclass()】: class com.it.aop.schema.Cat
- 使用 cglib 方式创建了 proxy 类
【proxy.toString()】: com.it.aop.schema.Cat@51acdf2e
【proxy.getClass().getCanonicalName()】: com.it.aop.schema.Cat$$EnhancerBySpringCGLIB$$42ce28ee
【proxy.getClass().getSuperclass()】: class com.it.aop.schema.Cat
- 使用 cglib 方式创建的代理类是Fish类的子类
String config = "classpath*:com/it/aop/schema/aop-schema.xml";
AbstractApplicationContext iocContainer = new ClassPathXmlApplicationContext(config);
Object proxy = iocContainer.getBean("fish");
System.out.println(proxy.toString());
System.out.println(proxy.getClass().getCanonicalName());
if (proxy instanceof flyable){
flyable fish = (flyable) proxy;
fish.fly();
}
iocContainer.close();
基于jdk下的动态proxy代理测试
- 主要涉及 java.lang.reflect 包中的 proxy类 和 InvocationHandler 接口
- 通过实现 InvocationHandler(内部是匿名内部类) 定义横切逻辑,并通过反射机制调用目标类的代码
- 动态地将横切逻辑和业务逻辑编织在一起
public static void main(String[] args) {
Prompter p = new Prompter();
// 代理目标
final Object target = new Airplane();
Class<?> targetClass = target.getClass(); //获取代理目标对应的类
ClassLoader loader = targetClass.getClassLoader(); // 获取 代理目标对应的类 的 "类加载器"
Class<?>[] interfaces = targetClass.getInterfaces(); // 获取 代理目标对应的类 所实现的接口
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null ;
try {
// 方位: 方法执行前
if( "fly".equals( method.getName() ) ) { // 在所有方法执行之前 、对 方法名称进行了筛选
p.before( method.getName() ); // Advice
}
// 方位: 方法执行前***: before
result = method.invoke(target, args); // 执行点 调用 target 所引用的对象的 method 表示的方法
// 方位: 方法正常执行前***: after
// 方位: 正常返回后 ( 绝对没有发生异常 )
} catch ( Exception e ) {
// 方位: 抛出异常后
e.printStackTrace();
}
// 方位: 方法执行后
if( "fly".equals( method.getName() ) ) { // 在所有方法执行之后 、对 方法名称进行了筛选
p.after( method.getName() ); // Advice
}
return result;
}
};
// 代理对象
Object proxy = Proxy.newProxyInstance( loader , interfaces , handler );
String s = proxy.toString(); // handler.invoke
System.out.println( s );
if( proxy instanceof Flyable ){
Flyable f = (Flyable) proxy;
f.fly();
}
}
- 产生的代理类以及代理类的父类测试结果
- 在基于JDK下代理,代理类的父类是 java.lang.reflect 类的子类
【proxy】: com.it.proxy.Factory@77b52d12
【proxy.getClass().getCanonicalName()】: com.sun.proxy.$Proxy0
【proxy.getClass().getSuperclass()】: class java.lang.reflect.Proxy
对于proxy代理类 内部的实现进行 猜想
```java
public interface flyable {
void fly();
}
public class Proxy {
protected InvocationHandler h ;
protected Proxy( InvocationHandler h ) {
this.h = h ;
}
//......
}
// 注意这里不考虑异常处理
public class $Proxy0 extends Proxy implements Nubia {
private static Method m0 ;
private static Method m1 ;
private static Method m2 ;
private static Method m3 ;
static {
Class<?> objectClass = Class.forName( "java.lang.Object" ) ;
m0 = objectClass.getDeclaredMethod( "equals" , Object.class );
m1 = objectClass.getDeclaredMethod( "toString" ) ;
m2 = objectClass.getDeclaredMethod( "hashCode" ) ;
Class<?> flyClass = Class.forName( "包名.flyable" ) ;
m3 = flyClass.getDeclaredMethod( "produce" );
}
public $Proxy0( InvocationHandler handler ){
super( handler );
}
public final boolean equals(Object another) {
Object[] args = { another };
return this.h.invoke( this , m0, args ); // m0 ==> equals
}
public final String toString() {
// 调用 InvocationHandler 实例的 invoke 方法时需要传入 三个参数:
// 第一个参数表示 代理对象 ( 当前对象 this 就是 代理对象 )
// 第二个参数表示 正在执行的方法 ( 就是 与当前的 toString 同名的方法 )
// 第三个参数表示 正在执行的方法 需要传入的参数 ( 如果没有参数,可以传一个 空数组 )
Object[] args = { };
return this.h.invoke( this , m1 , args ); // m1 ==> toString
}
public final int hashCode() {
Object[] args = { };
return this.h.invoke( this , m2, args ); // m2 ==> hashCode
}
public final Phone produce(){
Object[] args = { };
return this.h.invoke( this , m3, args ); // m3 ==> produce
}
}
- 在 ServiceAspect 类中通过 方法和注解 结合使用 定义 切点 , 方位 , Advice
[@Component](https://my.oschina.net/u/3907912)
[@Aspect](https://my.oschina.net/aspect)
public class ServiceAspect {
@Pointcut("execution(* com.it.aop.annotation.service.StudentService.save(..))")
public void servicePointcut(){
}
@Before("servicePointcut()")
public void before(JoinPoint joinPoint){
System.out.println("【"+joinPoint.getSignature().getName()+"】方法即将执行");
}
@After("servicePointcut()")
public void after(JoinPoint joinPoint){
System.out.println("【"+joinPoint.getSignature().getName()+"】方法即将结束");
}
@Around("servicePointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
String name = proceedingJoinPoint.getSignature().getName();
System.out.println( "开始为" + name + "计时" );
long begin = System.nanoTime();
Object result = proceedingJoinPoint.proceed();
long end = System.nanoTime();
System.out.print( "为" + name + "计时结束," );
System.out.println( "[ " + name + " ]执行耗时 [ " + ( end - begin ) + "ns, ]" );
return result;
}
@AfterReturning(pointcut = "servicePointcut()" , returning = "xx")
public void afterReturn (JoinPoint joinPoint , Object xx){
System.out.println(joinPoint.getSignature().getName()+"方法正常返回了"+xx);
}
@AfterThrowing( pointcut = "servicePointcut()" , throwing = "ex")
public void afterThrow( JoinPoint joinPoint , Throwable ex ) {
System.out.println("【 " + joinPoint.getSignature().getName() + " 】方法执行执行时抛出 【 " + ex +" 】");
}
}
今天的关于Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class的分享已经结束,谢谢您的关注,如果想了解更多关于159.234 OBJECT-ORIENTED PROGRAMMING、AlgorithmPartI:ProgrammingAssignment(2)、An Introduction to Protocol Oriented Programming in Swift、AOP(Aspect Oriented Programing) "面向切面编程"的相关知识,请在本站进行查询。
本文标签: