As we all know, among the JavaEE development frameworks , the Spring framework is the most used, and the positioning of annotations in the framework has become more and more obvious. Let’s make a joke: If it can be solved with one annotation, it will never be solved with a bunch of configuration and code; if it cannot be solved, then come with two annotations; (Hold on, don’t spray...)
1.@Component is a general annotation defined by Spring and can annotate any bean.
2.@Scope defines the scope of the bean. Its default scope is "singleton". In addition, there are prototype, request, session and global session.
BeanAnnotation class:
@Scope @Component public class BeanAnnotation { public void say(String arg) { System.out.println("BeanAnnotation : " + arg); } public void myHashCode() { System.out.println("BeanAnnotation : " + this.hashCode()); } }
junit4 test class→TestBeanAnnotation class:
@RunWith(BlockJUnit4ClassRunner.class) public class TestBeanAnnotation extends UnitTestBase { public TestBeanAnnotation() { super("classpath*:spring-beanannotation.xml"); } @Test public void testSay() { BeanAnnotation bean = super.getBean("beanAnnotation"); bean.say("This is test."); } @Test public void testScpoe() { BeanAnnotation bean = super.getBean("beanAnnotation"); bean.myHashCode(); bean = super.getBean("beanAnnotation"); bean.myHashCode(); } }
SpringConfiguration file→spring-beanannotation.xml:
<context:component-scan base-package="com.beanannotation"></context:component-scan>
Let’s analyze the Spring configuration file first, base- package="com.beanannotation"
indicates that we only process the annotations under this package name.
Then analyze the BeanAnnotation class and there is a say method. Assuming that we don't know what type of class this is (note: Service or DAO), we can use a general annotation @Component.
Finally analyze the TestBeanAnnotation class. In the testSay method, super.getBean("beanAnnotation")
retrieves the bean from the IOC container and calls the bean's say method.
It’s time to ask the question. When we super.getBean, we get it from the IOC container through the bean’s id. So what is this id? Because when we add @Component to the BeanAnnotation class, the default id is beanAnnotation. If the name of @Component is specified, for example, when it is specified as @Component("bean")
, the id obtained by super.getBean must be compared with it during unit test The test can be successful only if it corresponds.
Here I separate the @Scope annotation for analysis. There is a testScpoe method in the TestBeanAnnotation class. There is a myHashCode method in the BeanAnnotation class. You may be confused, why use this.hashCode()? Because @Scope specifies the scope of the bean, in order to ensure that the results of the test class are accurate and clear, the hash code value is used to determine whether it is the same object.
3.@Repository, @Service, and @Controller are more targeted annotations.
PS: Here we need to understand that these three annotations are based on the annotations defined by @Component:
①, @Repository is usually used to annotate DAO classes , which is what we often call the persistence layer.
②. @Service is usually used to annotate the Service class, which is the service layer.
③, @Controller is usually used in the Controller class, which is the control layer (MVC).
4.@Autowired is understood as the "traditional" setter method, which can be used in setter methods, constructors or member variables, and can perform automatic assembly of Spring Beans.
Spring configuration file → spring-beanannotation.xml:
<context:component-scan base-package="com.beanannotation"></context:component-scan>
SimpleMovie Lister class:
public class SimpleMovieLister { private MovieFinder movieFinder; @Autowired(required=false) public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } }
By default, if a suitable bean cannot be found, autowiring will failThrow an exception, we can @Autowired Annotate this set method and mark required=false to avoid it. However, this is not necessary. If the instance of movieFinder cannot be found, no exception will be thrown. Only when using it, it is found that movieFinder is null. In this case, we are required to When using it, first determine whether movieFinder is null. If so, a null pointer exception will be reported.
It is worth noting that we know that each class can have many constructors, but when using @Autowired, there is and can only be one constructor that can be marked as required=true (Note: required The default value is false).
BeanImplOne class:
@Order @Component public class BeanImplOne implements BeanInterface { }
BeanImplTwo class:
@Order @Component public class BeanImplTwo implements BeanInterface { }
BeanInterface class:
public interface BeanInterface { }
BeanInvoker class:
@Component public class BeanInvoker { @Autowired private List<BeanInterface> list; @Autowired private Map<String, BeanInterface> map; public void say() { if (null != list && 0 != list.size()) { for (BeanInterface bean : list) { System.out.println(bean.getClass().getName()); } } else { System.out.println(" list is null !"); } if (null != map && 0 != map.size()) { for (Map.Entry<String, BeanInterface> entry : map.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue().getClass().getName()); } } else { System.out.println("map is null !"); } } }
Test class TestInjection:
@RunWith(BlockJUnit4ClassRunner.class) public class TestInjection extends UnitTestBase { public TestInjection() { super("classpath:spring-beanannotation.xml"); } @Test public void testMultiBean() { BeanInvoker invoker = super.getBean("beanInvoker"); invoker.say(); } }
首先,我们清楚BeanImplOne类和BeanImplTwo类是实现了BeanInterface接口的,在BeanInvoker类里面我们定义了list和map,我们通过@Autowired注解把BeanImplOne类和BeanImplTwo类注解进入其中。那么怎么证实是@Autowired注解把这两个类注入到list或者map中的呢?那么请看if循环语句和foreach循环打印,通过这个逻辑判断,如果能够打印出BeanImplOne类和BeanImplTwo类的路径名,就说明这样是可以的。如果有些小伙伴可能不信,那么可以试着不使用@Autowired注解,看结果怎么样。
测试类没有什么好说的,各位小伙伴有没有注意到@Order注解呢?这里需要解释的就是,如果在@Order注解里面输入执行的数字,比如1或者2,那么打印出来的路径名就会按顺序,也就是说通过指定@Order注解的内容可以实现优先级的功能。
5.@ImportResource注解引入一个资源,对应一个xml文件
6.@Value注解从资源文件中,取出它的key并赋值给当前类的成员变量
MyDriverManager类:
public class MyDriverManager { public MyDriverManager(String url, String userName, String password) { System.out.println("url : " + url); System.out.println("userName: " + userName); System.out.println("password: " + password); } }
config.xml:
<context:property-placeholder location="classpath:/config.properties"/>
StoreConfig类:
@Configuration @ImportResource("classpath:config.xml") public class StoreConfig { @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public MyDriverManager myDriverManager() { return new MyDriverManager(url, username, password); }
这个案例我们使用注解配置jdbc数据库的连接,首先创建一个内含构造器的MyDriverManager类,然后配置config.xml里面的资源文件路径,以便@ImportResource注解获取,最后配置StoreConfig类。(注意url、username、password也必须要和数据库的保持一致哦)
详解StoreConfig类:首先我们定义三个成员变量,然后给每一个成员变量打上一个@value注解,注意@value里面的内容一定是资源文件里面的key值。这里的@ImportResource注解就是指明一个资源文件,在这个资源文件里面获取到对应的数据。那么@Configuration注解是用来干嘛的呢?为什么不用@Component注解呢?其实是这样的,@Component注解用于将所标注的类加载到 Spring 环境中,这时候是需要配置component-scan才能使用的,而@Configuration注解是Spring 3.X后提供的注解,它用于取代XML来配置 Spring。
7.@Bean注解用来标识配置和初始化一个由SpringIOC容器管理的新对象的方法,类似XML中配置文件的
ps:默认的@Bean注解是单例的,那么有什么方式可以指定它的范围呢?所以这里才出现了@Scope注解
8.@Scope注解,在@Scope注解里面value的范围和Bean的作用域是通用的,proxyMode的属性是采用哪一种的单例方式(一种是基于接口的注解,一种是基于类的代理)
@Bean @Scope(value ="session",proxyMode = "scopedProxyMode.TARGET_CLASS") public UserPreferences userPreferences(){ return new userPreferences(); } @Bean public service userService(){ UserService service =new SimpleUserService(); service.setUserPreferences(userPreferences); return service; }
The above is the detailed content of Detailed explanation of usage code examples of Spring framework annotations. For more information, please follow other related articles on the PHP Chinese website!