The Proxy Fairy, and The Magic of Spring Framework

VictorRentea 1,302 views 46 slides Apr 19, 2019
Slide 1
Slide 1 of 46
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46

About This Presentation

You can only claim you know Spring if you fully understand the Proxy design pattern, and how the framework uses it to do its magic. Join this live-coding session to explore 6 ways of intercepting method calls that you can use to cast your own spells and dramatically simplify your codebase.

Grab a s...


Slide Content

The Magic of Spring
The Proxy Fairy
Victor Rentea-Independent Trainer VictorRentea.ro @victorrentea

When something is painful
but you can't avoid doing it…
postpone it

When something is painful
but you can't avoid doing it…
delegate it

When something is painful
but you can't avoid doing it…
Do It More Often!
"Bring The Pain Forward!"

Continuous Integration
Pair Programming
Continuous Refactoring
TDD
XP
"Bring The Pain Forward!"

Victor Rentea
14 years of Java
Clean Code Evangelist
VictorRentea.ro
30+ talks, 12 meetups
.NET
Lead Architect
Tech Team Lead and Consultant
Software Craftsman
XP: Pair Programming, Refactoring, TDD

[email protected]@gmail.com
Independent
Technical Trainer & Coach
Hibernate Spring Java 8
Architecture, DDDDesign Patterns
Clean Code Unit Testing, TDD
Java Performance and much more…Scala
180+ days1300 devs6 years
[email protected]
30 companies
Posting daily on

▪Log the arguments passed to m1()
▪The same for m2(), please
▪And for m3,m4,...m30
▪I love it! I want the same
for allmethodsin this package
copy-paste
A Success Story
?!!...Argh!!... copy-paste...
You add a log.debug(...) in m1
You copy-pastein m2 and adjust it
Whaat?!!! ... copy-pastein 110 methods.
You feel bad. For 5 minutes.
Next task...
copy-paste
copy-paste
Time passes by

▪BUG: a method
is not logged !!!%@^!
Time passes by
(2 weeks later)
I’ll put this method here...
▪Please change the log formatOh boy! 1, 2, 3, .. 109, Done!
I my job!▪BUG: you missed a spot !!!%@^!
A Success Story

▪Log the arguments passed to m1()
▪The same for m2(), please
▪And for m3,m4,...m30
▪I love it! I want the same
for allmethodsin this package
copy-paste
A Success Story
?!!...Argh!!... copy-paste...
You add a log.debug(...) in m1
You copy-pastein m2 and adjust it
Whaat?!!! ... copy-pastein 110 methods.
You feel bad. For 5 minutes.
Next task...
copy-paste
copy-paste
Time passes by

copy-pasteNever logic
R
decompose it in smaller methods
and call them as you need
Don’t RepeatYourself
The Capital Sin in Programming
copy-pastecopy-paste
DY

What if I could magicaly
intercept method calls
and do stuff for each call ?
Aspect-OrientedProgramming
Logging
Transactions
Access Control
Audit
...
“Cross-cutting concerns”:
“But I will still need to addone line in each method!

placeholder intermediating interactions with an object
•The client wants to work with the Real Subject
•But we trick him to intercept his calls, to do
(1) AOP
(2) Remote calls (RMI, Web Services)
Proxy
«interface»
Subject
someMethod()
RealSubject
someMethod()
Proxy
someMethod()
represents
calls
actually uses
generated

do more thingsin an object’s methods, bycomposition
•Implement the Subject interface,
execute code before/after/instead calling the real method
➢Can be nested: new Decor1(new Decor2(original));
➢Usually written by hand
Decorator
Proxy
«interface»
Subject
someMethod()
RealSubject
someMethod()
Proxy
someMethod()
represents
calls
actually uses
Decorator
delegate
someMethod()

•Decorator + Proxy Patterns
•Interface Proxies
•Class Proxies
•In-depth Spring AOP
•Custom Aspects -Best Practices
Contents

Every time you don’t understand how Spring does something…
it's a Proxy
@Cacheable
@Transactional
@Aspect
@Async
@Secured
@Validated
Request/Thread scope

The Magic of Spring

classA {
private B b;
...
}
classBImpl
implementsB {
...
}
interfaceB {
...
}
Interface Proxy
has a
:A
B
:BImpl
implem
call
Static
Runtime
implem
proxy
Created at run-time with
java.lang.reflect.Proxy

classA {
private B b;
...
}
interfaceB {
...
}
Class Proxy
has a
:A
B
:B
call
Static
Runtime
proxy
Concrete classes are proxyied
via bytecode generation
classB {
extends
*
*

•A method of a non-Spring bean?
•A final method/class?
•For a class-proxy:
•Field access?
•A private method call?
Can AOP Intercept…
NO!
NO!
NO!
Well…
Actually…
You know…
You cando any of that via:
Bytecode Enhancement
(compile-time hacking)
Or Instrumentation
(classload-time hacking)
NO!

•Autowiringyourself ?
•@AutowiredApplicationContext+ getBean(T)
•@AutowiredObjectFactory<> + getObject()
•@Lookupmethod
•AopContext.currentProxy()
Call Yourself via a Proxy
To intercept a local call,
AopContext.currentProxy()

proxy
methodWithTx();
CurrentClassmyselfProxied=
(CurrentClass)AopContext.currentProxy();
myselfProxied.methodWithTx();
AopContext.currentProxy()
@Transactional(propagation = REQUIRES_NEW)
publicvoidmethodWithTx() {

No More Magic

-an AOP Alternative -
Functional Programming
"Execute Around" Pattern
transactionTemplate.execute(this::methodInNewTx);

I found mycode!
The Hamburger Problem
Proxies
What the heck is the rest?!
in front of any class with 1+ methods to intercept
Are you sure you want to know?
stacktrace

How can Aspects
(invisible logic)
communicate?
What is shared?
(within an invocation)
ThreadLocal
(invisible data)

ThreadLocalData--what about @Asynccalls?
Propagate Thread Data
to worker threads
Hunt me
afterwards

•Decorator + Proxy Patterns
•Interface Proxies
•Class Proxies
•In-depth Spring AOP
•Custom Aspects -Best Practices
Contents

@annotation(my.proj.Logged)
annotation-based weaving
Designing Custom Aspects -Best Practices
@Around("execution(* *(..)) && @within(my.proj.Facade))")
publicObject logAround(ProceedingJoinPointpoint) { … }
make them visible
@Facade
publicclassExpensiveOps{
@Logged
publicBoolean isPrime(intn) {…}
}

Designing Custom Aspects -Best Practices
"execution(* com.mycomp.proj.facade.*.*(..))"
instead of
package name
or
class name
"execution(* com.mycomp..*DAO.*(..))"
annotation-based weaving

keep them light
Designing Custom Aspects -Best Practices
synchronized
files
database
http
don't intercept insane-rate calls

Designing Custom Aspects -Best Practices
I did that!
don't intercept insane-rate calls
alternatives:
Execute-Around
FP
BeanPostProcessor
CPP

BPP
after init
@PostConstruct
BPP
before init
@Autowired
Designing Custom Aspects -Best Practices
BeanPostProcessor
new
*Technically, each step above hides a bit more work, and more ways to configure
Can return a different instanceproxy
WHY?

AverageError
(99.9%)Unit
Cache Method 357.7±11.7
us/op
Decorator 355.1 ±6.0
Interface Proxy398.7±28.0
Class Proxy 386.9±17.5
Class Proxy / BPP373.9±36.0
@Cacheable 8109.8±1097.5
Performance
Details? Run it yourself: https://github.com/victorrentea/proxy-fairy-performance

Leftover Tricks
Designing Custom Aspects -Best Practices
-Double proxying
-@Aspect @Order
-Sharing the PersistenceContext
-Proxies in ORMs
Hunt me
afterwards

Every time you don’t understand how Spring does something…
it's a Proxy
The Magic of Spring
mixins

Spring Data
mixins
CustomerRepository
Customer findByName(String name);
@Query("SELECT c FROM Cust... ")
List<Customer> getActiveCustomers();
JpaRepository<E,ID>
List<E> findAll();
E findOne(ID);
voidsave(E);
voiddelete(E); ...
CustomerRepositoryCustom
List<Customer> search(CustomerSearch);
CustomerRepositoryImpl
List<Customer> search(CustomerSearch) {
...<implem>...
}
YourBaseRepository<E,ID>
abccustomMethod(xyz);
YourBase
RepositoryImpl
<implem>
naming
rules

✓Proxy + Decorator Patterns; wiring
✓Interface & Class Proxy -under the hood
✓Spring AOP -tricks & limitations
✓Custom Aspects -Best Practices
Key Points

And have a nice Spring!
Thank You!
I'm available
a proof of seniority
I use both hemispheres
Tough meetings?
Abused estimates?
Purpose of code:
--Uncle Bob
1. Maintainable
2. Does its job!
Functional Party
Activist
Stay into
The Light
Trainings, Talks, GoodiesDaily Posts
Clean Code
needs strength
and determination
Let's chat!
Thanks for review,
Vladimir Sitnikov
Hunt me
down