比xml更好用的java annotation
DESCRIPTION
大綱- Java Annotation 基本概念- JavaEE6 annotation- 實戰應用 Java annotationTRANSCRIPT
JavaTWO JavaTWO 專業技術大會專業技術大會Java AnnotationJava Annotation李日貴李日貴 (jini)(jini)
About Me
• [email protected] ( jakarta99 )• SoftLeader Tech. Corp. President since 2002• Focus on dev in Java enterprise applications for
Insurances, Banking and Betting.• Researching and Sharing Java Opensources• My Google+ (http://gplus.to/jakarta99)• Single now
Agenda
• Introduction• Servlet 3.0• EJB 3.1• WebServices• CDI• Opensources• Javassist / ASM
@AnnotationCourse1
Introduction
What’s annotation
• Begin with “@” • An Interface• Set Values
– @Annotation– @Annotation(“someValue”)– @Annotation(var1=“someA”,var2=“someB”)– @Annotation(value={“Apple”, “Banana”,
“Cherry”})
RetentionPolicy
@Annotation Runtime
• Default value• Stereotype
– Find the classes contain @Annotation
– Initialize them as what you want
– To generate the codes or xml and etc..
@Target(ElementType)@AnnoTarget(TYPE)public class TheTarget {
@AnnoTarget(FIELD)private String globalMsg;@AnnoTarget(CONSTRUCTOR)public TheTarget() {
// This is a constructor}@AnnoTarget(METHOD)public void someMethod(@AnnoTarget (PARAMETER) String myParam) {
// This is a method}
}
@AnnotationCourse 2 Servlet 3.0
Servlet 2.5package javatwo.annotation;public class CatServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// do something}
}
web.xml<web-app>
<servlet><servlet-name>CatServlet</servlet-name><servlet-class>javatwo.annotation.CatServlet</servlet-class>
</servlet><servlet-mapping>
<servlet-name>CatServlet</servlet-name><url-pattern>/cat</url-pattern>
</servlet-mapping></web-app>
Servlet 3.0package javatwo.annotation;@WebServlet(“/cat”)public class CatServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// do something}
}
@WebServlet(name = "catServlet", urlPatterns = "/cat", initParams = { @WebInitParam(name = "name", value = "bobo") })
Servlet 3.0
• No web.xml needed– @WebServlet - Define a Servlet– @WebFilter - Define a Filter– @WebListener - Define a Listener– @WebInitParam- Define init parameter– @MultipartConfig- Define upload properties
• Can use web.xml to override values that specified by the Annotations.
FileUpload in Servlet 3.0@WebServlet(“/upload”)@MultipartConfig(location=“c:\\tmp”)public class FileUploadServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Collection<Part> parts = request.getParts();for( Part part:parts) {
part.write(“upload.txt”); // save to c:\tmp\upload.txt}
}
set Async in Servlet 3.0@WebServlet(name=“AsyncServlet”, urlPatterns=“/async”,
asyncSupported=“true”)public class AsyncServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
AsyncContext aCtx = request.startAsync(request, response); ServletContext sc = request.getServletContext();((Queue<AsyncContext>)sc.getAttribute(“slowQueue")).add(aCtx);
}}@WebListenerpublic class SlowQueueListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) { … }}
@AnnotationCourse 3 EJB 3.1
EJB 2.x1. public interface CalculatorLocal extends EJBLocalObject {..}2. public interface CalculatorLocalHome extends EJBLocalHome {..}3. public class CalculatorBean implements SessionBean { .. }4. ejb-jar.xml<ejb-jar>
<enterprise-beans><session>
<ejb-name>calculator</ejb-name><local-home>CalculatorLocalHome</local-home><local>CalculatorLocal</local><ejb-class>CalculatorBean</ejb-class><session-type>Stateless</session-type><transaction-type>Container</transaction-type>
</session></enterprise-beans>
</ejb-jar>
EJB 3.0
1. @Local public interface CalculatorLocal extends EJBLocalObject {..}
2. public interface CalculatorHome extends EJBHome {..}
3. @Stateless public class CalculatorBean implements CalculatorLocal{ .. }
4. ejb-jar.xml
EJB 3.1 (LocalBean)
1. @Local public interface CalculatorLocal extends EJBLocalObject {..}
2. public interface CalculatorHome extends EJBHome {..}
3. @Stateless public class CalculatorBean implements CalculatorLocal{ .. }
4. ejb-jar.xml
Singleton SessionBean@Singleton@ConcurrencyManagement(ConcurrencyManagementT
ype.CONTAINER)public class SingletonBean {
private int clickCount = 0;@Lock(LockType.WRITE)public int getClickCount() {
return clickCount++;}
}
//Thread-Safe, Transactional
Schedule Timer@Singletonpublic class TransFileBean {
@Schedule(minute=“0”,hour=“4”,dayOfMonth=“Last”)public void trans() {
// do transfer}
}
@AnnotationCourse 4
WebServices
WebServices
• “Big” WebServices– SOAP– JAX-WS– javax.jws.*
• RESTful WebServices– REST– JAX-RS– javax.ws.rs.*
SOAP WebServiceimport javax.jws.WebMethod;import javax.jws.WebService;
@WebService(serviceName=“helloService”)public class Hello {
@WebMethodpublic String sayHello(String name) {
return “Hello “+name;}
}
RESTful WebServiceimport javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;
@Path("/helloREST/{name}")public class HelloREST {
@GET@Produces(MediaType.TEXT_PLAIN)public String getHello(@PathParam("name") String name) {
return "Hello *"+name+"* from JAX-RS";}
}
@AnnotationCourse 5
CDI
Resource Injection JEE5@WebServlet(“/product”)public ProductServlet extends HttpServlet {
@Injectprivate ProductBean productBean;..
}
@Statelesspublic class ProductBean {
..}
Ambiguous Inject@Qualifierpublic @interface CarPolicyNo { }
@Qualifierpublic @interface FirePolicyNo { }
@CarPolicyNoGeneratorpublic class CarPolicyNoGenerator implements PolicyNoGenerator {.. }
@FirePolicyNoGeneratorpublic class FirePolicyNoGenerator implements PolicyNoGenerator{ .. }
public class FireService {@Inject@FirePolicyNoGeneratorprivate PolicyNoGenerator policyNoGenerator;
}
@Producespublic class DatabaseProducer {
@Produces @PersistenceContext(unitName=“ds1”)@FireDatabaseprivate EntityManager em;
}
public class FireService {@Inject @FireDatabaseprivate EntityManager em;
}
@AnnotationCourse 6
Opensources
jUnit 3.ximport junit.framework.Assert;import junit.framework.TestCase;
public class CalculateServiceTest3 extends TestCase {public void setUp() throws Exception { }public void testSum() {
int actual = new CalculateService().sum(3,5);Assert.assertEquals( 8 , actual );
}public void tearDown() throws Exception { }
}
jUnit 4.xpublic class CalculateServiceTest4 extends TestCase {
@BeforeClasspublic static void setUpBeforeClass() throws Exception { }@Beforepublic void beforeTest() throws Exception { }@Testpublic void theSum() {
Assert.assertEquals(8, new CalculateService().sum(3, 5)) ; } @Afterpublic void afterTest() throws Exception { }@AfterClasspublic static void tearDownAfterClass() throws Exception { }
}
Spring 2.5<beans>
<bean id=“newsDao” class=“javatwo.annotation.spring.NewsDao”/><bean id=“newsService” class=“javatwo.annotation.spring.NewsService”>
<property name=“newsDao”><ref bean=“newsDao”/>
</property></bean>
</beans>
@Servicepublic class NewsService {
@Autowiredprivate NewsDao newsDao;
}
Spring 3.0
@Namedpublic class NewsService {
@Injectprivate NewsDao newsDao;
}
Spring 3.0@Configurationpublic class AppConfig {
private @Value(“#{sysprop.dbURL}”) String dbURL;private @Value(“#{sysprop.username}”) String username;private @Value(“#{sysprop.password}”) String password;@Beanpublic DataSource dataSource() {
return new DriverManagerDataSource(dbURL, username, password );}
}
MVC in Spring3.0@Controller@RequestMapping(“/news”)public class NewsController {
@RequestMaaping(value=“{id}”, method=RequestMethod.GET) public ModelAndView getById(@PathVariable(“id”) Long id) {
return …}
}
@AnnotationCourse 7
Javassist / ASM
ReflectionClass myClass = MyClass.class;Method[] myMethods = myClass.getMethods();for(Method myMethod:myMethods) {
Annotation[] annotations = myMethod.getAnnotations();for( Annotation annotation:annotations) {
if( annotation instanceof MyAnno ) {MyAnno myAnno = (MyAnno) annotation;// do something
}}
}
Scan in ClassLoader• scannotation.sf.net project ( based on javassist )
URL[] urls = ClasspathUrlFinder.findClassPaths();AnnotationDB db = new AnnotationDB();db.scanArchives(urls);Map<String, Set<String>> annoIndex = db.getAnnotationIndex();Set<String> aClassNames =
annoIndex.get(“javatwo.annotation.MyAnno”);for( String aClassName:aClassNames ) {
..}// in Web,
WarUrlFinder.findWebInfClassesPath(this.getServletContext());
Get the Annotation valuesClassPool pool = ClassPool.getDefault();pool.insertClassPath(new ClassClassPath(this.getClass));CtClass cc = pool.get(aClassName);Object[] annos = cc.getAnnotations();for( Object anno : annos ) {
if( anno instanceof MyAnno ) {MyAnno myAnno = (MyAnno) anno;// do myAnno.var1(), myAnno.var2()
}}
Class R/W in ASMpublic class ScanMyDocVisitor implements ClassVisitor {
public AnnotationVisistor visitAnnotation(String desc, boolean visible) {}
}// in Controllerfor(String className: classNames){
ScanMyDocVisitor sv = new ScanMyDocVisitor();ClassReader cr = new ClassReader(Thread.currentThread().getContextClassLoader().getResouceAsStream(className));cr.accept(sv, 0);List<AnnotationNode> annotationList = sv.getVisibleAnnotations();..
}