2.ioc
@Configuration://配置,可以使用AnnotationConfigApplicationContext加載
@Import({Student.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})//全類名,MyImportSelector需要實現ImportSelector接口,MyImportBeanDefinitionRegistrar需要實現ImportBeanDefinitionRegistrar接口
@Value("李四") //指定值,可以用在set方法,參數,屬性上,支持spel表達式
@Bean(value="p1",destroyMethod = "destroy",initMethod = "init")/*注解具有返回值的方法,注入bean容器,destroy在銷毀bean之前,init在賦值之前,多實例不會加入bean容器管理,所以不會調用detroy方法*/
@PostConstruct//bean賦值完成之后
@PreDestroy//容器銷毀bean之前
@Autowired:自動注入,具有參數require,可以放在參數,方法,屬性,構造器上
@Resource與@Autowired用法類似,不支持@Primary的功能
@injection與@Autowired一樣,但是少了require屬性,需要導入jar
@Primary//默認是自動動裝配的首選bean,與@Autowired配合使用
@Scope:singleton為默認值,表示單實例,還有request,session,prototype
@Lookup://在單實例bean依賴多實例bean時使用,一般與@Scope配合使用
@PropertySource({"classpath:"})//導入多個資源文件,保存在環境變量中
@Conditional(WindowCondition.class)//需要實現Condition接口,滿足條件的才注冊bean,spring底層大量使用該注解,使用在方法上,表示當前方法需要滿足條件,注解在類上,表示所有的都需要滿足該條件
@Lazy //延遲加載,第一次調用時加載
@Qualifier("p")//指定注入bean的名稱
@component,@service,@repository,@controller
@Profile("test")/*默認值defalut,表示被ioc注入,其他值在沒有被激活的情況下,不能注入bean,用於數據源的切換等
注入方式:添加運行參數Dspring.profiles.active=test,或者按如下方式激活(按test方式激活)
@org.junit.Test public void testProfile(){ acac = new AnnotationConfigApplicationContext(); acac.getEnvironment().setActiveProfiles("test"); acac.register(MainConfig.class); acac.refresh(); String[] names = acac.getBeanDefinitionNames(); for (int i = 0; i < names.length; i++) { System.out.println(names[i]); } }
*/
@ComponentScans(): ComponentScan[] value();
@ComponentScan(value = "cn.springannocation.bean",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Component.class})}, useDefaultFilters = false)
/*屬性:useDefaultFilters:在includeFilters是需要使用,因為是默認加載 ; includeFilters/ excludeFilters*/
/*FilterType的枚舉值有:ANNOTATION:注解;ASSIGNABLE_TYPE:類型;ASPECTJ:切面表達式(很少用);REGEX:正則;CUSTOM:自定義(需要實現TypeFilter接口)*/
備注:
1)MyImportSelector實現ImportSelector接口,使用@Import({MyImportSelector.class})
public class MyImportSelector implements ImportSelector { //AnnotationMetadata:當前標注@Import的所有注解信息 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { String [] strs={"cn.springannocation.bean.Cat"};//全類名的方式 return strs;//不能返回null,否則會出異常,將strs中的內容注入到bean容器 } }
2)MyImportBeanDefinitionRegistrar實現ImportBeanDefinitionRegistrar接口,使用@Import({MyImportBeanDefinitionRegistrar.class})
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /*importingClassMetadata:當前標注@Import的所有注解信息 BeanDefinitionRegistry:使用registerBeanDefinition方法手動加載*/ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //RootBeanDefinition是BeanDefinition子類 RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Person.class); //Person注冊到BeanDefinitionRegistry中,手動注冊bean registry.registerBeanDefinition("name", rootBeanDefinition); } }
3)bean工廠
public class MyFactoryBean implements FactoryBean<Cat> { @Override//獲取bean public Cat getObject() throws Exception { return new Cat(); } @Override//獲取bean的類型 public Class<?> getObjectType() { return Cat.class; } @Override//是否是單例 public boolean isSingleton() { return true; } }
@Bean("myFactoryBean") public MyFactoryBean getMyFactoryBean() { return new MyFactoryBean(); }
@Test public void testFactoryBean(){ Object bean = acac.getBean("myFactoryBean"); System.out.println(bean.getClass());/輸出為class cn.springannocation.bean.Cat,會使用MyFactoryBean中的方法,在id前添加&表示返回的是工廠對象自身,生產對象*/ }
4)InitializingBean與DisposableBean//針對該bean
@Component("mad") public class MyInitializingBeanAndDisposableBean implements InitializingBean , DisposableBean { @Value("bb") String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override//賦值完成之后,@PostConstruct類似 public void afterPropertiesSet() throws Exception { setName("aaa"); System.out.println("afterPropertiesSet..."); } @Override//容器銷毀bean之前,@PreDestroy類似,在多實例中bean容器不會管理,所以不會調用destroy方法 public void destroy() throws Exception { System.out.println("destroySet..."); } @Override public String toString() { return "MyInitializingBeanAndDisposableBean{" + "name='" + name + '\'' + '}'; } }
6)WindowCondition實現Condition接口
public class WindowCondition implements Condition { /** * ConditionContext: 上下文信息 * AnnotatedTypeMetadata:注釋信息 */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//獲取bean工廠 ClassLoader classLoader = context.getClassLoader();//獲取類加載器 Environment environment = context.getEnvironment();//獲取上下文環境 BeanDefinitionRegistry registry = context.getRegistry();//獲取bean的注冊信息 registry.containsBeanDefinition("p");//容器中是否含有p if(environment.getProperty("os.name").contains("Windows")){ System.out.println(environment.getProperty("os.name")); return true; } return false; } }
7)FilterType.CUSTOM需要實現TypeFilter接口
/*自定義類型過濾器*/ public class MyTypeFilter implements TypeFilter { /*是一個一個來掃描添加的 * 返回值為true,那么就會添加到AnnotationConfigApplicationContext容器類 *metadataReader :當前正在掃描的類的信息,包含注解信息,類信息,資源信息等 *MetadataReaderFactory:可以獲取其他任何類的信息 * */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { System.out.println(metadataReader.getAnnotationMetadata());//注解信息 System.out.println(metadataReader.getClassMetadata());//類信息,例如類名含有xxx的加入容器等 System.out.println(metadataReader.getResource());//路徑等信息 return false; } }
8)xxxaware接口都有相應的xxxawreprocessor接口,每個xxxaware接口都有一個需要實現的方法
BeanClassLoaderAware bean加載器接口
ApplicationContextAware 注入對象
BeanNameAware bean的名稱
BeanFactoryAware bean工廠
EmbeddedValueResolverAware 解析spel表達式等
3.aop
@EnableAspectJAutoProxy//開啟切面aop
@Enablexxx都是切面的配置
@Aspect//表示當前類為一個切面類,基本都與@Component一起使用
@before,@after,@Pointcut,@Around ,@AfterThrowing, @AfterRunning
execution表達式語法:
execution (“modifiers-pattern ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throw-pattern”)
說明:execution:匹配執方法的連接點
modifiers-pattern 權限修飾符 支持通配* 可省略
ret-type-pattern 返回值類型 支持通配*
declaring-type-pattern指定方法所屬的類 支持通配* 可省略
name-pattern方法名 支持通配
param-pattern ..代表兩個任意的參數假如是*則是代表一個任意類型的參數
throw-pattern 聲明拋出異常 支持通配 可省略
@Before("execution(* spring2.*.*(int, int))")第一個*表示返回類型 第二個*表示類名 第三個表示方法
備注:
1)AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar //public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)//自定義導入組件
4)事務
@EnableTransactionManagement:開啟事務
@Transactional //默認值transactionManager, propagation,isolation,readOnly,rollbackFor,noRollbackFor,timeout(spring中有說明)
4.servlet
1)web每次運行的時候都會掃描meta-inf下的javax.servlet.ServletContainerInitializer文件
實例:如下javax.servlet.ServletContainerInitializer文件
內容cn.springannocation.service.MyServletContainerInitializer
//在servlet8.2.4中看到在在meta-inf建立services下建立一個javax.servlet.ServletContainerInitializer文件, // 在文件內寫全路徑,默認servlet運行時會自動加載 //滿足@HandlesTypes的類型的子類,實現類的類型(不包含自身),放入Set<Class<?>> c中 @HandlesTypes(value = {}) public class MyServletContainerInitializer implements ServletContainerInitializer { @Override //啟動是就會運行onStartup方法 //必須在項目啟動的時候添加 public void onStartup(Set<Class<?>> c, ServletContext sc) throws ServletException { FilterRegistration.Dynamic userFilter = sc.addFilter("userFilter", new UserFilter()); userFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),true,"/*"); //可以注冊servlet listen filter } }
5.springmvc注解
@EnableWebMvc // <mvc:annotation-driven/>,且開啟定制功能
WebMvcConfigurer接口的實現類WebMvcConfigurerAdapter
方法
addFormatters 注冊類型轉換器
addInterceptors 注冊攔截器
configureViewResolvers 視圖解析器
configureDefaultServletHandling 靜態資源的處理等
6.web3.0異步請求處理
在web3.0以前,從require獲取線程,到response釋放線程是一個線程//可能造成線程線程不能釋放導致線程不足。
@WebServlet(value = "async", asyncSupported = true)// asyncSupported = true支持異步
@WebServlet(value = "async",asyncSupported = true)//asyncSupported = true開啟異步 public class AsyncServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AsyncContext startAsync = req.startAsync(); startAsync.start(new Runnable() { @Override public void run() { AsyncContext asyncContext = req.getAsyncContext(); // asyncContext.addListener();添加監聽 // asyncContext.setTimeout();連接時間 ServletResponse response = asyncContext.getResponse(); try { response.getWriter().print("hellowrold"); } catch (IOException e) { e.printStackTrace(); } } }); } }
springmvc的異步
@RequestMapping("/async") //當返回值為Callable的時候springmvc會自動的開啟一個異步的處理 //Callable返回的結果,springmvc將再次放入容器,恢復之前的處理,所以會使用兩次攔截器 //有主線程池和異步線程池 public Callable<String> async(){ Callable<String> callable = new Callable(){ @Override public Object call() throws Exception { return "async"; } }; return callable; }
test
@RequestMapping("/deferredResult") public DeferredResult<String> deferredResult(){ DeferredResult<String> result = new DeferredResult<>((long)2000,"sss"); MyQueue.save(result); return result;//deferredResult.setResult(oder);觸發以后,才能得到真正的返回 } @RequestMapping("/create") public String create(){ //UUID是16字節128位長的數字,它是在一定的范圍內(從特定的名字空間到全球)唯一的機器生成的標識符 //為了保證UUID的唯一性,規范定義了包括網卡MAC地址、時間戳、名字空間(Namespace)、隨機或偽隨機數、 // 時序等元素,以及從這些元素生成UUID的算法。UUID的復雜特性在保證了其唯一性的同時,意味着只能由計算機生成 String oder= UUID.randomUUID().toString(); DeferredResult deferredResult = MyQueue.poll(); deferredResult.setResult(oder);//這里觸發以后, 上述的return result才立即真正的返回; return "success"; }
public class MyQueue { private static ConcurrentLinkedQueue<DeferredResult> queue=new ConcurrentLinkedQueue<>();//基於分片機制管理鎖,效率較LinkedQueue高 public static void save (DeferredResult deferredResult){ queue.add(deferredResult); } public static DeferredResult poll(){ DeferredResult deferredResult = queue.poll(); return deferredResult; } }
備注:其他注解鍵spring